diff --git a/runtime/history/SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4.json b/runtime/history/SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4.json
new file mode 100644
index 00000000..b025e02a
--- /dev/null
+++ b/runtime/history/SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4.json
@@ -0,0 +1,38 @@
+{
+ "schema_version": 1,
+ "channel": "homelab-runtime",
+ "command_id": "SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4",
+ "status": "OK",
+ "rc": 0,
+ "host": "pve01",
+ "mode": "read-only",
+ "component": "gram-support-service-worker-source-rca-readonly",
+ "started_at_utc": "2026-09-18T06:16:22Z",
+ "finished_at_utc": "2026-09-18T06:16:23Z",
+ "reference_register_checked": true,
+ "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66",
+ "error_register_checked": true,
+ "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0",
+ "command_sha256": "628189b0b18497cabb62b75d0fb6506209677e28954b6201c862bba85c776534",
+ "duplicate_failed_command_blocked": false,
+ "block_reason": null,
+ "execution_started": true,
+ "change_declared": false,
+ "result_contract_valid": true,
+ "result_contract_status": null,
+ "result_contract_error": null,
+ "command_rc": 0,
+ "changes_made": false,
+ "rollback_started": false,
+ "rollback_restored": null,
+ "mutation_outcome": "NO_MUTATION",
+ "sanitized": true,
+ "secrets_included": false,
+ "private_addresses_included": false,
+ "raw_evidence_retained_locally": true,
+ "raw_evidence_sha256": "9742e5b94ef98a5dfa64fc2efe1dfef47880eaffad20efdf2bf9b72b47f7b6d6",
+ "sanitized_output_sha256": "9742e5b94ef98a5dfa64fc2efe1dfef47880eaffad20efdf2bf9b72b47f7b6d6",
+ "output_truncated_in_json": false,
+ "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
+ "output": "GRAM516R5RCA4_SAFE_REPORT={\"err_truncated\":false,\"guest\":{\"core\":[{\"matches\":[{\"sep\":true},{\"line\":125,\"text\":\"\\t\\tswitch (get_class($reply))\"},{\"line\":126,\"text\":\"\\t\\t{\"},{\"line\":127,\"text\":\"\\t\\t\\tcase Redirect::class:\"},{\"line\":128,\"text\":\"\\t\\t\\tcase Reroute::class:\"},{\"line\":129,\"text\":\"\\t\\t\\t\\treturn false; // don't update anything, assume the next page will do it\"},{\"line\":130,\"text\":\"\"},{\"line\":131,\"text\":\"\\t\\t\\tcase Message::class:\"},{\"line\":132,\"text\":\"\\t\\t\\tcase View::class:\"},{\"line\":133,\"text\":\"\\t\\t\\t\\t$viewState = 'valid';\"},{\"line\":134,\"text\":\"\\t\\t\\t\\tbreak;\"},{\"line\":135,\"text\":\"\\t\\t}\"},{\"line\":136,\"text\":\"\"},{\"line\":137,\"text\":\"\\t\\tif ($reply->getResponseCode() >= 400)\"},{\"line\":138,\"text\":\"\\t\\t{\"},{\"line\":139,\"text\":\"\\t\\t\\t$viewState = 'error';\"},{\"line\":140,\"text\":\"\\t\\t}\"},{\"line\":141,\"text\":\"\"},{\"line\":142,\"text\":\"\\t\\treturn true;\"},{\"line\":143,\"text\":\"\\t}\"},{\"line\":144,\"text\":\"\"},{\"line\":145,\"text\":\"\\tpublic function checkTfaRedirect()\"},{\"line\":146,\"text\":\"\\t{\"},{\"line\":147,\"text\":\"\\t\\t$session = $this->session();\"},{\"line\":148,\"text\":\"\\t\\tif ($session->tfaLoginRedirect)\"},{\"line\":149,\"text\":\"\\t\\t{\"},{\"sep\":true},{\"line\":219,\"text\":\"\\tpublic function assertNotDisabled($action)\"},{\"line\":220,\"text\":\"\\t{\"},{\"line\":221,\"text\":\"\\t\\tif (\\\\XF::visitor()->user_state == 'disabled')\"},{\"line\":222,\"text\":\"\\t\\t{\"},{\"line\":223,\"text\":\"\\t\\t\\tthrow $this->exception(\"},{\"line\":224,\"text\":\"\\t\\t\\t\\t$this->plugin(ErrorPlugin::class)->actionDisabled()\"},{\"line\":225,\"text\":\"\\t\\t\\t);\"},{\"line\":226,\"text\":\"\\t\\t}\"},{\"line\":227,\"text\":\"\\t}\"},{\"line\":228,\"text\":\"\"},{\"line\":229,\"text\":\"\\tpublic function assertCanonicalBaseUrl($action)\"},{\"line\":230,\"text\":\"\\t{\"},{\"line\":231,\"text\":\"\\t\\tif ($this->responseType != 'html')\"},{\"line\":232,\"text\":\"\\t\\t{\"},{\"line\":233,\"text\":\"\\t\\t\\treturn;\"},{\"line\":234,\"text\":\"\\t\\t}\"},{\"line\":235,\"text\":\"\"},{\"line\":236,\"text\":\"\\t\\tif (!$this->request->isGet() && !$this->request->isHead())\"},{\"line\":237,\"text\":\"\\t\\t{\"},{\"line\":238,\"text\":\"\\t\\t\\treturn;\"},{\"line\":239,\"text\":\"\\t\\t}\"},{\"line\":240,\"text\":\"\"},{\"line\":241,\"text\":\"\\t\\t$options = $this->options();\"},{\"line\":242,\"text\":\"\\t\\tif (!$options->boardUrlCanonical)\"},{\"line\":243,\"text\":\"\\t\\t{\"},{\"sep\":true},{\"line\":273,\"text\":\"\"},{\"line\":274,\"text\":\"\\t\\t\\tthrow $this->exception($reply);\"},{\"line\":275,\"text\":\"\\t\\t}\"},{\"line\":276,\"text\":\"\\t}\"},{\"line\":277,\"text\":\"\"},{\"line\":278,\"text\":\"\\tpublic function assertBoardActive($action)\"},{\"line\":279,\"text\":\"\\t{\"},{\"line\":280,\"text\":\"\\t\\t$options = $this->options();\"},{\"line\":281,\"text\":\"\\t\\tif (!$options->boardActive && !\\\\XF::visitor()->is_admin)\"},{\"line\":282,\"text\":\"\\t\\t{\"},{\"line\":283,\"text\":\"\\t\\t\\t$reply = $this->message(new PreEscaped($options->boardInactiveMessage), $this->app->config('serviceUnavailableCode'));\"},{\"line\":284,\"text\":\"\\t\\t\\t$reply->setPageParam('skipSidebarWidgets', true);\"},{\"line\":285,\"text\":\"\\t\\t\\t$reply->setResponseHeader('Retry-After', 60);\"},{\"line\":286,\"text\":\"\\t\\t\\t$reply->setResponseHeader('Refresh', 60);\"},{\"line\":287,\"text\":\"\"},{\"line\":288,\"text\":\"\\t\\t\\tthrow $this->exception($reply);\"},{\"line\":289,\"text\":\"\\t\\t}\"},{\"line\":290,\"text\":\"\\t}\"},{\"line\":291,\"text\":\"\"},{\"line\":292,\"text\":\"\\tpublic function assertTfaRequirement($action)\"},{\"line\":293,\"text\":\"\\t{\"},{\"line\":294,\"text\":\"\\t\\t$visitor = \\\\XF::visitor();\"},{\"line\":295,\"text\":\"\\t\\tif ($visitor->user_id\"},{\"line\":296,\"text\":\"\\t\\t\\t&& empty($visitor->Option->use_tfa)\"},{\"line\":297,\"text\":\"\\t\\t\\t&& \\\\XF::config('enableTfa')\"},{\"line\":298,\"text\":\"\\t\\t\\t&& $visitor->hasPermission('general', 'requireTfa')\"},{\"sep\":true},{\"line\":459,\"text\":\"\\t\\treturn in_array($requestRoutePath, $whitelistRoutePaths, true);\"},{\"line\":460,\"text\":\"\\t}\"},{\"line\":461,\"text\":\"\"},{\"line\":462,\"text\":\"\\tpublic function isEmbeddedImageRequest(): bool\"},{\"line\":463,\"text\":\"\\t{\"},{\"line\":464,\"text\":\"\\t\\treturn $this->request->isEmbeddedImageRequest();\"},{\"line\":465,\"text\":\"\\t}\"},{\"line\":466,\"text\":\"\"},{\"line\":467,\"text\":\"\\tpublic function assertNotEmbeddedImageRequest()\"},{\"line\":468,\"text\":\"\\t{\"},{\"line\":469,\"text\":\"\\t\\tif ($this->isEmbeddedImageRequest())\"},{\"line\":470,\"text\":\"\\t\\t{\"},{\"line\":471,\"text\":\"\\t\\t\\t$this->setResponseType('raw');\"},{\"line\":472,\"text\":\"\"},{\"line\":473,\"text\":\"\\t\\t\\t$view = $this->view('XF:Error\\\\EmbeddedImageRequest');\"},{\"line\":474,\"text\":\"\\t\\t\\t$view->setResponseCode(406);\"},{\"line\":475,\"text\":\"\"},{\"line\":476,\"text\":\"\\t\\t\\tthrow $this->exception($view);\"},{\"line\":477,\"text\":\"\\t\\t}\"},{\"line\":478,\"text\":\"\\t}\"},{\"line\":479,\"text\":\"\"},{\"line\":480,\"text\":\"\\tpublic function hasContentPendingApproval()\"},{\"line\":481,\"text\":\"\\t{\"},{\"line\":482,\"text\":\"\\t\\t$pendingUntil = $this->session()->hasContentPendingUntil;\"},{\"line\":483,\"text\":\"\\t\\treturn ($pendingUntil && $pendingUntil >= \\\\XF::$time);\"},{\"line\":484,\"text\":\"\\t}\"},{\"line\":485,\"text\":\"\"},{\"line\":486,\"text\":\"\\tprotected function isDiscouraged()\"},{\"sep\":true},{\"line\":565,\"text\":\"\\tpublic function assertNotFlooding($action, $floodingLimit = null)\"},{\"line\":566,\"text\":\"\\t{\"},{\"line\":567,\"text\":\"\\t\\t$visitor = \\\\XF::visitor();\"},{\"line\":568,\"text\":\"\\t\\tif ($visitor->hasPermission('general', 'bypassFloodCheck'))\"},{\"line\":569,\"text\":\"\\t\\t{\"},{\"line\":570,\"text\":\"\\t\\t\\treturn;\"},{\"line\":571,\"text\":\"\\t\\t}\"},{\"line\":572,\"text\":\"\"},{\"line\":573,\"text\":\"\\t\\t$floodChecker = $this->service(FloodCheckService::class);\"},{\"line\":574,\"text\":\"\\t\\t$timeRemaining = $floodChecker->checkFlooding($action, $visitor->user_id, $floodingLimit);\"},{\"line\":575,\"text\":\"\\t\\tif ($timeRemaining)\"},{\"line\":576,\"text\":\"\\t\\t{\"},{\"line\":577,\"text\":\"\\t\\t\\tthrow $this->exception($this->responseFlooding($timeRemaining));\"},{\"line\":578,\"text\":\"\\t\\t}\"},{\"line\":579,\"text\":\"\\t}\"},{\"line\":580,\"text\":\"\"},{\"line\":581,\"text\":\"\\tpublic function responseFlooding($floodSeconds)\"},{\"line\":582,\"text\":\"\\t{\"},{\"line\":583,\"text\":\"\\t\\treturn $this->error(\\\\XF::phrase('must_wait_x_seconds_before_performing_this_action', ['count' => $floodSeconds]));\"},{\"line\":584,\"text\":\"\\t}\"},{\"line\":585,\"text\":\"\"},{\"line\":586,\"text\":\"\\tpublic function isRobot()\"},{\"line\":587,\"text\":\"\\t{\"},{\"line\":588,\"text\":\"\\t\\treturn boolval($this->request->getRobotName());\"},{\"line\":589,\"text\":\"\\t}\"},{\"line\":590,\"text\":\"\"},{\"line\":591,\"text\":\"\\t/**\"},{\"line\":592,\"text\":\"\\t * @return IpRepository\"},{\"line\":593,\"text\":\"\\t */\"}],\"path\":\"src/XF/Pub/Controller/AbstractController.php\",\"present\":true,\"sha256\":\"023efffff88cd1675173f30a8104d25fb220a5d8dc989d89c33d3ba09b0c0169\"}],\"error\":null,\"files\":[{\"matches\":[],\"path\":\"Pub/Controller/Support.php\",\"present\":true,\"sha256\":\"6cb34b1d27e9f0132263637cefa62fe0e998a9a86620b7ac33199f41ee86f9d4\"},{\"matches\":[],\"path\":\"Pub/Controller/StaffSupport.php\",\"present\":true,\"sha256\":\"6852bd0061d6e118851673bfd4099e2b22e6291bf09f429820740844996f93f9\"},{\"matches\":[{\"sep\":true},{\"line\":1,\"text\":\"\"},{\"line\":2,\"text\":\"\"},{\"line\":3,\"text\":\" \"},{\"line\":4,\"text\":\" \"},{\"line\":5,\"text\":\" \"},{\"line\":6,\"text\":\" \"},{\"line\":7,\"text\":\"\"}],\"path\":\"_data/routes.xml\",\"present\":true,\"sha256\":\"c80e6b0f7153993915d8bbc8ee6b36e6386b00bb1865d6aff050f9c1fd1f0302\"},{\"matches\":[{\"sep\":true},{\"line\":553,\"text\":\"<xf:if is=\\\"$xf.options.gramSupportSiteId\\\">\"},{\"line\":554,\"text\":\"\\t<a class=\\\"gramSupport-launcher button button--primary\\\"\"},{\"line\":555,\"text\":\"\\t\\thref=\\\"{{ link('support/create') }}\\\"\"},{\"line\":556,\"text\":\"\\t\\taria-label=\\\"{{ phrase('gram_support_open_support') }}\\\">\"},{\"line\":557,\"text\":\"\\t\\t{{ phrase('gram_support_open_support') }}\"},{\"line\":558,\"text\":\"\\t</a>\"},{\"line\":559,\"text\":\"</xf:if>\"},{\"line\":560,\"text\":\"\"},{\"line\":561,\"text\":\" <xf:title>{{ phrase('gram_support_staff_queue') }}</xf:title>\"},{\"line\":562,\"text\":\"<xf:css src=\\\"gram_support.less\\\" />\"},{\"line\":563,\"text\":\"<span class=\\\"js-gramSupportPwaConfig\\\" hidden\"},{\"line\":564,\"text\":\"\\tdata-manifest-url=\\\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\\\"\"},{\"line\":565,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"></span>\"},{\"line\":566,\"text\":\"<xf:js addon=\\\"Gram/Support\\\" src=\\\"gram/support/staff-pwa.js\\\" min=\\\"1\\\" />\"},{\"line\":567,\"text\":\"\"},{\"line\":568,\"text\":\"<div class=\\\"block\\\">\"},{\"line\":569,\"text\":\"\\t<div class=\\\"block-container\\\">\"},{\"line\":570,\"text\":\"\\t\\t<div class=\\\"block-body\\\">\"},{\"line\":571,\"text\":\"\\t\\t\\t<xf:foreach loop=\\\"$tickets\\\" value=\\\"$ticket\\\">\"},{\"line\":572,\"text\":\"\\t\\t\\t\\t<div class=\\\"block-row\\\">\"},{\"line\":573,\"text\":\"\\t\\t\\t\\t\\t<a href=\\\"{{ link('support/staff/ticket', null, {'ref': $ticket.public_ref}) }}\\\">\"},{\"line\":574,\"text\":\"\\t\\t\\t\\t\\t\\t{{ $ticket.public_ref }} \\u2014 {{ $ticket.subject }}\"},{\"line\":575,\"text\":\"\\t\\t\\t\\t\\t</a>\"},{\"line\":576,\"text\":\"\\t\\t\\t\\t\\t<span class=\\\"u-muted\\\">\"},{\"line\":577,\"text\":\"<xf:if is=\\\"$ticket.status == 'NEW'\\\">\\u041d\\u043e\\u0432\\u044b\\u0439\"},{\"sep\":true},{\"line\":579,\"text\":\"<xf:elseif is=\\\"$ticket.status == 'WAITING_USER'\\\" />\\u041e\\u0436\\u0438\\u0434\\u0430\\u0435\\u0442 \\u043e\\u0442\\u0432\\u0435\\u0442\\u0430 \\u043f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044f\"},{\"line\":580,\"text\":\"<xf:elseif is=\\\"$ticket.status == 'RESOLVED'\\\" />\\u0420\\u0435\\u0448\\u0451\\u043d\"},{\"line\":581,\"text\":\"<xf:elseif is=\\\"$ticket.status == 'CLOSED'\\\" />\\u0417\\u0430\\u043a\\u0440\\u044b\\u0442\"},{\"line\":582,\"text\":\"<xf:else />{{ $ticket.status }}\"},{\"line\":583,\"text\":\"</xf:if>\"},{\"line\":584,\"text\":\"</span>\"},{\"line\":585,\"text\":\"\\t\\t\\t\\t</div>\"},{\"line\":586,\"text\":\"\\t\\t\\t</xf:foreach>\"},{\"line\":587,\"text\":\"\\t\\t</div>\"},{\"line\":588,\"text\":\"\\t</div>\"},{\"line\":589,\"text\":\"</div>\"},{\"line\":590,\"text\":\"\"},{\"line\":591,\"text\":\" 'use strict';\"},{\"line\":592,\"text\":\"\"},{\"line\":593,\"text\":\"const OFFLINE_URL = '{{ base_url('js/gram/support/pwa/offline.html')|escape('js') }}';\"},{\"line\":594,\"text\":\"const STATIC_CACHE = 'gram-support-staff-static-v1';\"},{\"line\":595,\"text\":\"\"},{\"line\":596,\"text\":\"self.addEventListener('install', event => {\"},{\"line\":597,\"text\":\"\\tevent.waitUntil(\"},{\"line\":598,\"text\":\"\\t\\tcaches.open(STATIC_CACHE)\"},{\"line\":599,\"text\":\"\\t\\t\\t.then(cache => cache.addAll([OFFLINE_URL]))\"},{\"line\":600,\"text\":\"\\t\\t\\t.then(() => self.skipWaiting())\"},{\"line\":601,\"text\":\"\\t);\"},{\"line\":602,\"text\":\"});\"},{\"line\":603,\"text\":\"\"},{\"sep\":true},{\"line\":655,\"text\":\"\\t\\t\\t\\t\\treturn response;\"},{\"line\":656,\"text\":\"\\t\\t\\t\\t});\"},{\"line\":657,\"text\":\"\\t\\t\\t\\treturn cached || network;\"},{\"line\":658,\"text\":\"\\t\\t\\t})\"},{\"line\":659,\"text\":\"\\t\\t)\"},{\"line\":660,\"text\":\"\\t);\"},{\"line\":661,\"text\":\"});\"},{\"line\":662,\"text\":\"\"},{\"line\":663,\"text\":\" <xf:title>{{ phrase('gram_support_staff_ticket') }} {{ $ticket.public_ref }}</xf:title>\"},{\"line\":664,\"text\":\"<xf:css src=\\\"gram_support.less\\\" />\"},{\"line\":665,\"text\":\"<span class=\\\"js-gramSupportPwaConfig\\\" hidden\"},{\"line\":666,\"text\":\"\\tdata-manifest-url=\\\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\\\"\"},{\"line\":667,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"></span>\"},{\"line\":668,\"text\":\"<xf:js addon=\\\"Gram/Support\\\" src=\\\"gram/support/staff-pwa.js\\\" min=\\\"1\\\" />\"},{\"line\":669,\"text\":\"\"},{\"line\":670,\"text\":\"<div class=\\\"block\\\">\"},{\"line\":671,\"text\":\"\\t<div class=\\\"block-container\\\">\"},{\"line\":672,\"text\":\"\\t\\t<h2 class=\\\"block-header\\\">{{ $ticket.public_ref }} \\u2014 {{ $ticket.subject }}</h2>\"},{\"line\":673,\"text\":\"\\t\\t<div class=\\\"block-body\\\">\"},{\"line\":674,\"text\":\"\\t\\t\\t<xf:foreach loop=\\\"$messages\\\" value=\\\"$message\\\">\"},{\"line\":675,\"text\":\"\\t\\t\\t\\t<div class=\\\"block-row {{ $message.is_internal ? 'gramSupport-message--internal' : '' }}\\\">\"},{\"line\":676,\"text\":\"\\t\\t\\t\\t\\t<div class=\\\"gramSupport-messageMeta\\\">\"},{\"line\":677,\"text\":\"\\t\\t\\t\\t\\t\\t{{ date_time($message.message_date) }}\"},{\"line\":678,\"text\":\"\\t\\t\\t\\t\\t\\t<xf:if is=\\\"$message.is_internal\\\"> \\u00b7 {{ phrase('gram_support_internal_note') }}</xf:if>\"},{\"line\":679,\"text\":\"\\t\\t\\t\\t\\t</div>\"}],\"path\":\"_data/templates.xml\",\"present\":true,\"sha256\":\"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239\"},{\"matches\":[],\"path\":\"addon.json\",\"present\":true,\"sha256\":\"566f1739937088517f5ef0dd2d20bc92460084028180c16502931fa86057aea5\"}],\"occurrences\":[{\"hit_count\":2,\"hits\":[{\"line\":25,\"text\":\" 'Gram\\\\Support:PwaServiceWorker',\"},{\"line\":26,\"text\":\" 'gram_support_staff_service_worker',\"}],\"path\":\"Pub/Controller/Pwa.php\",\"sha256\":\"9e3217d9524349a8137b89d418e4693ca17f8e5f61ba5b563fff747d1014efb3\"},{\"hit_count\":2,\"hits\":[{\"line\":5,\"text\":\"class PwaServiceWorker extends \\\\XF\\\\Mvc\\\\View\"},{\"line\":12,\"text\":\" 'public:gram_support_staff_service_worker',\"}],\"path\":\"Pub/View/PwaServiceWorker.php\",\"sha256\":\"700f01f005b818d63267e70dac7669a606c78fabbef5d3e01731c49db3d0be04\"},{\"hit_count\":1,\"hits\":[{\"line\":6,\"text\":\" \"}],\"path\":\"_data/routes.xml\",\"sha256\":\"c80e6b0f7153993915d8bbc8ee6b36e6386b00bb1865d6aff050f9c1fd1f0302\"},{\"hit_count\":3,\"hits\":[{\"line\":565,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"></span>\"},{\"line\":591,\"text\":\" 'use strict';\"},{\"line\":667,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"></span>\"}],\"path\":\"_data/templates.xml\",\"sha256\":\"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239\"},{\"hit_count\":1,\"hits\":[{\"line\":30,\"text\":\" \\\"src/addons/Gram/Support/Pub/View/PwaServiceWorker.php\\\": \\\"700f01f005b818d63267e70dac7669a606c78fabbef5d3e01731c49db3d0be04\\\",\"}],\"path\":\"hashes.json\",\"sha256\":\"1f947a585ee5d5936c6d1c73a7d4602c0f77ceafd98936df74b89a6a4538921f\"}],\"ok\":true},\"guest_stderr_present\":false,\"inner_rc\":0,\"ok\":true,\"out_truncated\":false,\"transport_rc\":0,\"transport_stderr_bytes\":0,\"transport_stderr_sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"}\nGRAM516R5RCA4_DECISION=PASS_SERVICE_WORKER_SOURCE_EVIDENCE_CAPTURED\nGRAM516R5RCA4_NEXT_GATE=BUILD_EXACT_SERVICE_WORKER_FIX\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n"
+}
diff --git a/runtime/history/SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4.txt b/runtime/history/SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4.txt
new file mode 100644
index 00000000..2ce947a5
--- /dev/null
+++ b/runtime/history/SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4.txt
@@ -0,0 +1,36 @@
+CHAT_OUTPUT_BEGIN
+COMMAND_ID=SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4
+STATUS=OK
+RC=0
+HOST=pve01
+MODE=read-only
+COMPONENT=gram-support-service-worker-source-rca-readonly
+REFERENCE_REGISTER_CHECK=OK
+REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
+ERROR_REGISTER_CHECK=OK
+ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
+COMMAND_SHA256=628189b0b18497cabb62b75d0fb6506209677e28954b6201c862bba85c776534
+DUPLICATE_FAILED_COMMAND_BLOCKED=false
+EXECUTION_STARTED=true
+CHANGE_DECLARED=false
+RESULT_CONTRACT_VALID=true
+RESULT_CONTRACT_STATUS=NOT_APPLICABLE
+RESULT_CONTRACT_ERROR=NONE
+COMMAND_RC=0
+CHANGES_MADE=false
+ROLLBACK_STARTED=false
+ROLLBACK_RESTORED=null
+MUTATION_OUTCOME=NO_MUTATION
+SANITIZED=yes
+SECRETS_INCLUDED=no
+PRIVATE_ADDRESSES_INCLUDED=no
+RAW_EVIDENCE_SHA256=9742e5b94ef98a5dfa64fc2efe1dfef47880eaffad20efdf2bf9b72b47f7b6d6
+SANITIZED_OUTPUT_SHA256=9742e5b94ef98a5dfa64fc2efe1dfef47880eaffad20efdf2bf9b72b47f7b6d6
+OUTPUT_BEGIN
+GRAM516R5RCA4_SAFE_REPORT={"err_truncated":false,"guest":{"core":[{"matches":[{"sep":true},{"line":125,"text":"\t\tswitch (get_class($reply))"},{"line":126,"text":"\t\t{"},{"line":127,"text":"\t\t\tcase Redirect::class:"},{"line":128,"text":"\t\t\tcase Reroute::class:"},{"line":129,"text":"\t\t\t\treturn false; // don't update anything, assume the next page will do it"},{"line":130,"text":""},{"line":131,"text":"\t\t\tcase Message::class:"},{"line":132,"text":"\t\t\tcase View::class:"},{"line":133,"text":"\t\t\t\t$viewState = 'valid';"},{"line":134,"text":"\t\t\t\tbreak;"},{"line":135,"text":"\t\t}"},{"line":136,"text":""},{"line":137,"text":"\t\tif ($reply->getResponseCode() >= 400)"},{"line":138,"text":"\t\t{"},{"line":139,"text":"\t\t\t$viewState = 'error';"},{"line":140,"text":"\t\t}"},{"line":141,"text":""},{"line":142,"text":"\t\treturn true;"},{"line":143,"text":"\t}"},{"line":144,"text":""},{"line":145,"text":"\tpublic function checkTfaRedirect()"},{"line":146,"text":"\t{"},{"line":147,"text":"\t\t$session = $this->session();"},{"line":148,"text":"\t\tif ($session->tfaLoginRedirect)"},{"line":149,"text":"\t\t{"},{"sep":true},{"line":219,"text":"\tpublic function assertNotDisabled($action)"},{"line":220,"text":"\t{"},{"line":221,"text":"\t\tif (\\XF::visitor()->user_state == 'disabled')"},{"line":222,"text":"\t\t{"},{"line":223,"text":"\t\t\tthrow $this->exception("},{"line":224,"text":"\t\t\t\t$this->plugin(ErrorPlugin::class)->actionDisabled()"},{"line":225,"text":"\t\t\t);"},{"line":226,"text":"\t\t}"},{"line":227,"text":"\t}"},{"line":228,"text":""},{"line":229,"text":"\tpublic function assertCanonicalBaseUrl($action)"},{"line":230,"text":"\t{"},{"line":231,"text":"\t\tif ($this->responseType != 'html')"},{"line":232,"text":"\t\t{"},{"line":233,"text":"\t\t\treturn;"},{"line":234,"text":"\t\t}"},{"line":235,"text":""},{"line":236,"text":"\t\tif (!$this->request->isGet() && !$this->request->isHead())"},{"line":237,"text":"\t\t{"},{"line":238,"text":"\t\t\treturn;"},{"line":239,"text":"\t\t}"},{"line":240,"text":""},{"line":241,"text":"\t\t$options = $this->options();"},{"line":242,"text":"\t\tif (!$options->boardUrlCanonical)"},{"line":243,"text":"\t\t{"},{"sep":true},{"line":273,"text":""},{"line":274,"text":"\t\t\tthrow $this->exception($reply);"},{"line":275,"text":"\t\t}"},{"line":276,"text":"\t}"},{"line":277,"text":""},{"line":278,"text":"\tpublic function assertBoardActive($action)"},{"line":279,"text":"\t{"},{"line":280,"text":"\t\t$options = $this->options();"},{"line":281,"text":"\t\tif (!$options->boardActive && !\\XF::visitor()->is_admin)"},{"line":282,"text":"\t\t{"},{"line":283,"text":"\t\t\t$reply = $this->message(new PreEscaped($options->boardInactiveMessage), $this->app->config('serviceUnavailableCode'));"},{"line":284,"text":"\t\t\t$reply->setPageParam('skipSidebarWidgets', true);"},{"line":285,"text":"\t\t\t$reply->setResponseHeader('Retry-After', 60);"},{"line":286,"text":"\t\t\t$reply->setResponseHeader('Refresh', 60);"},{"line":287,"text":""},{"line":288,"text":"\t\t\tthrow $this->exception($reply);"},{"line":289,"text":"\t\t}"},{"line":290,"text":"\t}"},{"line":291,"text":""},{"line":292,"text":"\tpublic function assertTfaRequirement($action)"},{"line":293,"text":"\t{"},{"line":294,"text":"\t\t$visitor = \\XF::visitor();"},{"line":295,"text":"\t\tif ($visitor->user_id"},{"line":296,"text":"\t\t\t&& empty($visitor->Option->use_tfa)"},{"line":297,"text":"\t\t\t&& \\XF::config('enableTfa')"},{"line":298,"text":"\t\t\t&& $visitor->hasPermission('general', 'requireTfa')"},{"sep":true},{"line":459,"text":"\t\treturn in_array($requestRoutePath, $whitelistRoutePaths, true);"},{"line":460,"text":"\t}"},{"line":461,"text":""},{"line":462,"text":"\tpublic function isEmbeddedImageRequest(): bool"},{"line":463,"text":"\t{"},{"line":464,"text":"\t\treturn $this->request->isEmbeddedImageRequest();"},{"line":465,"text":"\t}"},{"line":466,"text":""},{"line":467,"text":"\tpublic function assertNotEmbeddedImageRequest()"},{"line":468,"text":"\t{"},{"line":469,"text":"\t\tif ($this->isEmbeddedImageRequest())"},{"line":470,"text":"\t\t{"},{"line":471,"text":"\t\t\t$this->setResponseType('raw');"},{"line":472,"text":""},{"line":473,"text":"\t\t\t$view = $this->view('XF:Error\\EmbeddedImageRequest');"},{"line":474,"text":"\t\t\t$view->setResponseCode(406);"},{"line":475,"text":""},{"line":476,"text":"\t\t\tthrow $this->exception($view);"},{"line":477,"text":"\t\t}"},{"line":478,"text":"\t}"},{"line":479,"text":""},{"line":480,"text":"\tpublic function hasContentPendingApproval()"},{"line":481,"text":"\t{"},{"line":482,"text":"\t\t$pendingUntil = $this->session()->hasContentPendingUntil;"},{"line":483,"text":"\t\treturn ($pendingUntil && $pendingUntil >= \\XF::$time);"},{"line":484,"text":"\t}"},{"line":485,"text":""},{"line":486,"text":"\tprotected function isDiscouraged()"},{"sep":true},{"line":565,"text":"\tpublic function assertNotFlooding($action, $floodingLimit = null)"},{"line":566,"text":"\t{"},{"line":567,"text":"\t\t$visitor = \\XF::visitor();"},{"line":568,"text":"\t\tif ($visitor->hasPermission('general', 'bypassFloodCheck'))"},{"line":569,"text":"\t\t{"},{"line":570,"text":"\t\t\treturn;"},{"line":571,"text":"\t\t}"},{"line":572,"text":""},{"line":573,"text":"\t\t$floodChecker = $this->service(FloodCheckService::class);"},{"line":574,"text":"\t\t$timeRemaining = $floodChecker->checkFlooding($action, $visitor->user_id, $floodingLimit);"},{"line":575,"text":"\t\tif ($timeRemaining)"},{"line":576,"text":"\t\t{"},{"line":577,"text":"\t\t\tthrow $this->exception($this->responseFlooding($timeRemaining));"},{"line":578,"text":"\t\t}"},{"line":579,"text":"\t}"},{"line":580,"text":""},{"line":581,"text":"\tpublic function responseFlooding($floodSeconds)"},{"line":582,"text":"\t{"},{"line":583,"text":"\t\treturn $this->error(\\XF::phrase('must_wait_x_seconds_before_performing_this_action', ['count' => $floodSeconds]));"},{"line":584,"text":"\t}"},{"line":585,"text":""},{"line":586,"text":"\tpublic function isRobot()"},{"line":587,"text":"\t{"},{"line":588,"text":"\t\treturn boolval($this->request->getRobotName());"},{"line":589,"text":"\t}"},{"line":590,"text":""},{"line":591,"text":"\t/**"},{"line":592,"text":"\t * @return IpRepository"},{"line":593,"text":"\t */"}],"path":"src/XF/Pub/Controller/AbstractController.php","present":true,"sha256":"023efffff88cd1675173f30a8104d25fb220a5d8dc989d89c33d3ba09b0c0169"}],"error":null,"files":[{"matches":[],"path":"Pub/Controller/Support.php","present":true,"sha256":"6cb34b1d27e9f0132263637cefa62fe0e998a9a86620b7ac33199f41ee86f9d4"},{"matches":[],"path":"Pub/Controller/StaffSupport.php","present":true,"sha256":"6852bd0061d6e118851673bfd4099e2b22e6291bf09f429820740844996f93f9"},{"matches":[{"sep":true},{"line":1,"text":""},{"line":2,"text":""},{"line":3,"text":" "},{"line":4,"text":" "},{"line":5,"text":" "},{"line":6,"text":" "},{"line":7,"text":""}],"path":"_data/routes.xml","present":true,"sha256":"c80e6b0f7153993915d8bbc8ee6b36e6386b00bb1865d6aff050f9c1fd1f0302"},{"matches":[{"sep":true},{"line":553,"text":"<xf:if is=\"$xf.options.gramSupportSiteId\">"},{"line":554,"text":"\t<a class=\"gramSupport-launcher button button--primary\""},{"line":555,"text":"\t\thref=\"{{ link('support/create') }}\""},{"line":556,"text":"\t\taria-label=\"{{ phrase('gram_support_open_support') }}\">"},{"line":557,"text":"\t\t{{ phrase('gram_support_open_support') }}"},{"line":558,"text":"\t</a>"},{"line":559,"text":"</xf:if>"},{"line":560,"text":""},{"line":561,"text":" <xf:title>{{ phrase('gram_support_staff_queue') }}</xf:title>"},{"line":562,"text":"<xf:css src=\"gram_support.less\" />"},{"line":563,"text":"<span class=\"js-gramSupportPwaConfig\" hidden"},{"line":564,"text":"\tdata-manifest-url=\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\""},{"line":565,"text":"\tdata-sw-url=\"{{ link('support/service-worker') }}\"></span>"},{"line":566,"text":"<xf:js addon=\"Gram/Support\" src=\"gram/support/staff-pwa.js\" min=\"1\" />"},{"line":567,"text":""},{"line":568,"text":"<div class=\"block\">"},{"line":569,"text":"\t<div class=\"block-container\">"},{"line":570,"text":"\t\t<div class=\"block-body\">"},{"line":571,"text":"\t\t\t<xf:foreach loop=\"$tickets\" value=\"$ticket\">"},{"line":572,"text":"\t\t\t\t<div class=\"block-row\">"},{"line":573,"text":"\t\t\t\t\t<a href=\"{{ link('support/staff/ticket', null, {'ref': $ticket.public_ref}) }}\">"},{"line":574,"text":"\t\t\t\t\t\t{{ $ticket.public_ref }} \u2014 {{ $ticket.subject }}"},{"line":575,"text":"\t\t\t\t\t</a>"},{"line":576,"text":"\t\t\t\t\t<span class=\"u-muted\">"},{"line":577,"text":"<xf:if is=\"$ticket.status == 'NEW'\">\u041d\u043e\u0432\u044b\u0439"},{"sep":true},{"line":579,"text":"<xf:elseif is=\"$ticket.status == 'WAITING_USER'\" />\u041e\u0436\u0438\u0434\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f"},{"line":580,"text":"<xf:elseif is=\"$ticket.status == 'RESOLVED'\" />\u0420\u0435\u0448\u0451\u043d"},{"line":581,"text":"<xf:elseif is=\"$ticket.status == 'CLOSED'\" />\u0417\u0430\u043a\u0440\u044b\u0442"},{"line":582,"text":"<xf:else />{{ $ticket.status }}"},{"line":583,"text":"</xf:if>"},{"line":584,"text":"</span>"},{"line":585,"text":"\t\t\t\t</div>"},{"line":586,"text":"\t\t\t</xf:foreach>"},{"line":587,"text":"\t\t</div>"},{"line":588,"text":"\t</div>"},{"line":589,"text":"</div>"},{"line":590,"text":""},{"line":591,"text":" 'use strict';"},{"line":592,"text":""},{"line":593,"text":"const OFFLINE_URL = '{{ base_url('js/gram/support/pwa/offline.html')|escape('js') }}';"},{"line":594,"text":"const STATIC_CACHE = 'gram-support-staff-static-v1';"},{"line":595,"text":""},{"line":596,"text":"self.addEventListener('install', event => {"},{"line":597,"text":"\tevent.waitUntil("},{"line":598,"text":"\t\tcaches.open(STATIC_CACHE)"},{"line":599,"text":"\t\t\t.then(cache => cache.addAll([OFFLINE_URL]))"},{"line":600,"text":"\t\t\t.then(() => self.skipWaiting())"},{"line":601,"text":"\t);"},{"line":602,"text":"});"},{"line":603,"text":""},{"sep":true},{"line":655,"text":"\t\t\t\t\treturn response;"},{"line":656,"text":"\t\t\t\t});"},{"line":657,"text":"\t\t\t\treturn cached || network;"},{"line":658,"text":"\t\t\t})"},{"line":659,"text":"\t\t)"},{"line":660,"text":"\t);"},{"line":661,"text":"});"},{"line":662,"text":""},{"line":663,"text":" <xf:title>{{ phrase('gram_support_staff_ticket') }} {{ $ticket.public_ref }}</xf:title>"},{"line":664,"text":"<xf:css src=\"gram_support.less\" />"},{"line":665,"text":"<span class=\"js-gramSupportPwaConfig\" hidden"},{"line":666,"text":"\tdata-manifest-url=\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\""},{"line":667,"text":"\tdata-sw-url=\"{{ link('support/service-worker') }}\"></span>"},{"line":668,"text":"<xf:js addon=\"Gram/Support\" src=\"gram/support/staff-pwa.js\" min=\"1\" />"},{"line":669,"text":""},{"line":670,"text":"<div class=\"block\">"},{"line":671,"text":"\t<div class=\"block-container\">"},{"line":672,"text":"\t\t<h2 class=\"block-header\">{{ $ticket.public_ref }} \u2014 {{ $ticket.subject }}</h2>"},{"line":673,"text":"\t\t<div class=\"block-body\">"},{"line":674,"text":"\t\t\t<xf:foreach loop=\"$messages\" value=\"$message\">"},{"line":675,"text":"\t\t\t\t<div class=\"block-row {{ $message.is_internal ? 'gramSupport-message--internal' : '' }}\">"},{"line":676,"text":"\t\t\t\t\t<div class=\"gramSupport-messageMeta\">"},{"line":677,"text":"\t\t\t\t\t\t{{ date_time($message.message_date) }}"},{"line":678,"text":"\t\t\t\t\t\t<xf:if is=\"$message.is_internal\"> \u00b7 {{ phrase('gram_support_internal_note') }}</xf:if>"},{"line":679,"text":"\t\t\t\t\t</div>"}],"path":"_data/templates.xml","present":true,"sha256":"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239"},{"matches":[],"path":"addon.json","present":true,"sha256":"566f1739937088517f5ef0dd2d20bc92460084028180c16502931fa86057aea5"}],"occurrences":[{"hit_count":2,"hits":[{"line":25,"text":" 'Gram\\Support:PwaServiceWorker',"},{"line":26,"text":" 'gram_support_staff_service_worker',"}],"path":"Pub/Controller/Pwa.php","sha256":"9e3217d9524349a8137b89d418e4693ca17f8e5f61ba5b563fff747d1014efb3"},{"hit_count":2,"hits":[{"line":5,"text":"class PwaServiceWorker extends \\XF\\Mvc\\View"},{"line":12,"text":" 'public:gram_support_staff_service_worker',"}],"path":"Pub/View/PwaServiceWorker.php","sha256":"700f01f005b818d63267e70dac7669a606c78fabbef5d3e01731c49db3d0be04"},{"hit_count":1,"hits":[{"line":6,"text":" "}],"path":"_data/routes.xml","sha256":"c80e6b0f7153993915d8bbc8ee6b36e6386b00bb1865d6aff050f9c1fd1f0302"},{"hit_count":3,"hits":[{"line":565,"text":"\tdata-sw-url=\"{{ link('support/service-worker') }}\"></span>"},{"line":591,"text":" 'use strict';"},{"line":667,"text":"\tdata-sw-url=\"{{ link('support/service-worker') }}\"></span>"}],"path":"_data/templates.xml","sha256":"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239"},{"hit_count":1,"hits":[{"line":30,"text":" \"src/addons/Gram/Support/Pub/View/PwaServiceWorker.php\": \"700f01f005b818d63267e70dac7669a606c78fabbef5d3e01731c49db3d0be04\","}],"path":"hashes.json","sha256":"1f947a585ee5d5936c6d1c73a7d4602c0f77ceafd98936df74b89a6a4538921f"}],"ok":true},"guest_stderr_present":false,"inner_rc":0,"ok":true,"out_truncated":false,"transport_rc":0,"transport_stderr_bytes":0,"transport_stderr_sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}
+GRAM516R5RCA4_DECISION=PASS_SERVICE_WORKER_SOURCE_EVIDENCE_CAPTURED
+GRAM516R5RCA4_NEXT_GATE=BUILD_EXACT_SERVICE_WORKER_FIX
+HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null}
+
+OUTPUT_END
+CHAT_OUTPUT_END
diff --git a/runtime/latest.json b/runtime/latest.json
index 4b61ff7b..b025e02a 100644
--- a/runtime/latest.json
+++ b/runtime/latest.json
@@ -1,19 +1,19 @@
{
"schema_version": 1,
"channel": "homelab-runtime",
- "command_id": "SUPPORT-260918-GRAM-SUPPORT-CODEVIPE-ERROR-REQUESTSTATE-RCA-READONLY-516R5RCA3",
+ "command_id": "SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4",
"status": "OK",
"rc": 0,
"host": "pve01",
"mode": "read-only",
- "component": "gram-support-codevipe-error-requeststate-rca-readonly",
- "started_at_utc": "2026-09-18T06:12:40Z",
- "finished_at_utc": "2026-09-18T06:12:41Z",
+ "component": "gram-support-service-worker-source-rca-readonly",
+ "started_at_utc": "2026-09-18T06:16:22Z",
+ "finished_at_utc": "2026-09-18T06:16:23Z",
"reference_register_checked": true,
"reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66",
"error_register_checked": true,
"error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0",
- "command_sha256": "af3e7b5d91ef4c593cbdf0d032ab8022f0bfb2da04c29aafb6bd450f1e99caf7",
+ "command_sha256": "628189b0b18497cabb62b75d0fb6506209677e28954b6201c862bba85c776534",
"duplicate_failed_command_blocked": false,
"block_reason": null,
"execution_started": true,
@@ -30,9 +30,9 @@
"secrets_included": false,
"private_addresses_included": false,
"raw_evidence_retained_locally": true,
- "raw_evidence_sha256": "7de025dbfa44e4f0c49d03b4428121cbefb1c0b7b624db402a0f60b938a6ec98",
- "sanitized_output_sha256": "7de025dbfa44e4f0c49d03b4428121cbefb1c0b7b624db402a0f60b938a6ec98",
+ "raw_evidence_sha256": "9742e5b94ef98a5dfa64fc2efe1dfef47880eaffad20efdf2bf9b72b47f7b6d6",
+ "sanitized_output_sha256": "9742e5b94ef98a5dfa64fc2efe1dfef47880eaffad20efdf2bf9b72b47f7b6d6",
"output_truncated_in_json": false,
"full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
- "output": "GRAM516R5RCA3_SAFE_REPORT={\"err_truncated\":false,\"guest\":{\"error\":null,\"ok\":true,\"php_rc\":0,\"php_stderr_bytes\":0,\"php_stderr_sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"runtime\":{\"error\":null,\"error_count\":4,\"error_max\":4,\"ok\":true,\"rows\":[{\"error_id\":4,\"exception_type\":\"TypeError\",\"filename_basename\":\"Response.php\",\"line\":490,\"message\":\"strlen(): Argument #1 ($string) must be of type string, XF\\\\Http\\\\Response given\",\"request_state\":{\"bytes\":160,\"collection_keys\":{\"_GET\":[\"/support/service-worker\"],\"_POST\":[]},\"fields\":{\"referrer\":{\"host\":\"codevipe.ru\",\"path\":\"/support/staff/ticket\"},\"url\":{\"host\":null,\"path\":\"/support/service-worker\"}},\"format\":\"json\",\"sha256\":\"bf0540e9fdbe13a7e735692f32f0ebe88e3d872ce50068b9165a7546eef32fdf\",\"top_keys\":[\"url\",\"referrer\",\"_GET\",\"_POST\"]},\"time_utc\":\"2026-09-18T05:58:47+00:00\",\"trace_head\":\"#0 src/XF/Http/Response.php(293): XF\\\\Http\\\\Response->sendBody()\\n#1 src/XF.php(894): XF\\\\Http\\\\Response->send(Object(XF\\\\Http\\\\Request))\\n#2 index.php(23): XF::runApp('XF\\\\\\\\Pub\\\\\\\\App')\\n#3 {main}\"},{\"error_id\":3,\"exception_type\":\"TypeError\",\"filename_basename\":\"Response.php\",\"line\":490,\"message\":\"strlen(): Argument #1 ($string) must be of type string, XF\\\\Http\\\\Response given\",\"request_state\":{\"bytes\":160,\"collection_keys\":{\"_GET\":[\"/support/service-worker\"],\"_POST\":[]},\"fields\":{\"referrer\":{\"host\":\"codevipe.ru\",\"path\":\"/support/staff/ticket\"},\"url\":{\"host\":null,\"path\":\"/support/service-worker\"}},\"format\":\"json\",\"sha256\":\"bf0540e9fdbe13a7e735692f32f0ebe88e3d872ce50068b9165a7546eef32fdf\",\"top_keys\":[\"url\",\"referrer\",\"_GET\",\"_POST\"]},\"time_utc\":\"2026-09-18T05:58:32+00:00\",\"trace_head\":\"#0 src/XF/Http/Response.php(293): XF\\\\Http\\\\Response->sendBody()\\n#1 src/XF.php(894): XF\\\\Http\\\\Response->send(Object(XF\\\\Http\\\\Request))\\n#2 index.php(23): XF::runApp('XF\\\\\\\\Pub\\\\\\\\App')\\n#3 {main}\"},{\"error_id\":2,\"exception_type\":\"TypeError\",\"filename_basename\":\"Response.php\",\"line\":490,\"message\":\"strlen(): Argument #1 ($string) must be of type string, XF\\\\Http\\\\Response given\",\"request_state\":{\"bytes\":160,\"collection_keys\":{\"_GET\":[\"/support/service-worker\"],\"_POST\":[]},\"fields\":{\"referrer\":{\"host\":\"codevipe.ru\",\"path\":\"/support/staff/ticket\"},\"url\":{\"host\":null,\"path\":\"/support/service-worker\"}},\"format\":\"json\",\"sha256\":\"bf0540e9fdbe13a7e735692f32f0ebe88e3d872ce50068b9165a7546eef32fdf\",\"top_keys\":[\"url\",\"referrer\",\"_GET\",\"_POST\"]},\"time_utc\":\"2026-09-18T05:58:26+00:00\",\"trace_head\":\"#0 src/XF/Http/Response.php(293): XF\\\\Http\\\\Response->sendBody()\\n#1 src/XF.php(894): XF\\\\Http\\\\Response->send(Object(XF\\\\Http\\\\Request))\\n#2 index.php(23): XF::runApp('XF\\\\\\\\Pub\\\\\\\\App')\\n#3 {main}\"},{\"error_id\":1,\"exception_type\":\"TypeError\",\"filename_basename\":\"Response.php\",\"line\":490,\"message\":\"strlen(): Argument #1 ($string) must be of type string, XF\\\\Http\\\\Response given\",\"request_state\":{\"bytes\":137,\"collection_keys\":{\"_GET\":[\"/support/service-worker\"],\"_POST\":[]},\"fields\":{\"referrer\":{\"host\":\"codevipe.ru\",\"path\":\"/support/staff\"},\"url\":{\"host\":null,\"path\":\"/support/service-worker\"}},\"format\":\"json\",\"sha256\":\"c809fa5b352e5cabae7067d8626171f788a8dd768fe250455dae052ff2489348\",\"top_keys\":[\"url\",\"referrer\",\"_GET\",\"_POST\"]},\"time_utc\":\"2026-09-18T05:54:03+00:00\",\"trace_head\":\"#0 src/XF/Http/Response.php(293): XF\\\\Http\\\\Response->sendBody()\\n#1 src/XF.php(894): XF\\\\Http\\\\Response->send(Object(XF\\\\Http\\\\Request))\\n#2 index.php(23): XF::runApp('XF\\\\\\\\Pub\\\\\\\\App')\\n#3 {main}\"}]},\"source\":{\"Gram/Support/Pub/Controller/StaffSupport.php\":{\"basename\":\"StaffSupport.php\",\"matches\":[{\"sep\":true},{\"line\":20,\"text\":\"\"},{\"line\":21,\"text\":\" if (!$visitor->user_id || !$allowed)\"},{\"line\":22,\"text\":\" {\"},{\"line\":23,\"text\":\" throw $this->exception($this->noPermission());\"},{\"line\":24,\"text\":\" }\"},{\"line\":25,\"text\":\" }\"},{\"line\":26,\"text\":\"\"},{\"line\":27,\"text\":\" public function actionIndex()\"},{\"line\":28,\"text\":\" {\"},{\"line\":29,\"text\":\" $this->assertStaff(false);\"},{\"line\":30,\"text\":\"\"},{\"line\":31,\"text\":\" $tickets = $this->repository('Gram\\\\Support:Ticket')\"},{\"line\":32,\"text\":\" ->findStaffQueue()\"},{\"line\":33,\"text\":\" ->fetch();\"},{\"line\":34,\"text\":\"\"},{\"line\":35,\"text\":\" return $this->view(\"},{\"line\":36,\"text\":\" 'Gram\\\\Support:StaffQueue',\"},{\"line\":37,\"text\":\" 'gram_support_staff_queue',\"},{\"line\":38,\"text\":\" ['tickets' => $tickets]\"},{\"line\":39,\"text\":\" );\"},{\"line\":40,\"text\":\" }\"},{\"line\":41,\"text\":\"\"},{\"line\":42,\"text\":\" public function actionTicket()\"},{\"line\":43,\"text\":\" {\"},{\"line\":44,\"text\":\" $this->assertStaff(false);\"},{\"line\":45,\"text\":\" $ticket = $this->assertTicket();\"},{\"line\":46,\"text\":\"\"},{\"line\":47,\"text\":\" $messages = $this->repository('Gram\\\\Support:Message')\"},{\"line\":48,\"text\":\" ->findAllForTicket((int)$ticket->ticket_id)\"},{\"line\":49,\"text\":\" ->fetch();\"},{\"line\":50,\"text\":\"\"},{\"line\":51,\"text\":\" return $this->view(\"},{\"line\":52,\"text\":\" 'Gram\\\\Support:StaffTicket',\"},{\"line\":53,\"text\":\" 'gram_support_staff_ticket',\"},{\"line\":54,\"text\":\" [\"},{\"line\":55,\"text\":\" 'ticket' => $ticket,\"},{\"line\":56,\"text\":\" 'messages' => $messages,\"},{\"line\":57,\"text\":\" 'statusOptions' => StatusPolicy::all()\"},{\"line\":58,\"text\":\" ]\"},{\"line\":59,\"text\":\" );\"},{\"line\":60,\"text\":\" }\"},{\"line\":61,\"text\":\"\"},{\"line\":62,\"text\":\" public function actionReply()\"},{\"line\":63,\"text\":\" {\"},{\"line\":64,\"text\":\" $this->assertPostOnly();\"},{\"line\":65,\"text\":\" $this->assertStaff(true);\"},{\"line\":66,\"text\":\"\"},{\"line\":67,\"text\":\" $ticket = $this->assertTicket();\"},{\"line\":68,\"text\":\" $isInternal = (bool)$this->filter('is_internal', 'bool');\"},{\"line\":69,\"text\":\"\"},{\"line\":70,\"text\":\" if ($isInternal\"},{\"line\":71,\"text\":\" && !\\\\XF::visitor()->hasPermission('gramSupport', 'internalNotes'))\"},{\"line\":72,\"text\":\" {\"},{\"line\":73,\"text\":\" return $this->noPermission();\"},{\"line\":74,\"text\":\" }\"},{\"line\":75,\"text\":\"\"},{\"line\":76,\"text\":\" /** @var Reply $reply */\"},{\"line\":77,\"text\":\" $reply = $this->service(Reply::class);\"},{\"line\":78,\"text\":\" $reply->add(\"},{\"line\":79,\"text\":\" $ticket,\"},{\"line\":80,\"text\":\" $this->filter('message', 'str'),\"},{\"line\":81,\"text\":\" true,\"},{\"line\":82,\"text\":\" $isInternal\"},{\"line\":83,\"text\":\" );\"},{\"line\":84,\"text\":\"\"},{\"line\":85,\"text\":\" return $this->redirect(\"},{\"line\":86,\"text\":\" $this->buildLink('support/staff/ticket', null, ['ref' => $ticket->public_ref])\"},{\"line\":87,\"text\":\" );\"},{\"line\":88,\"text\":\" }\"},{\"line\":89,\"text\":\"\"},{\"line\":90,\"text\":\" public function actionUpdate()\"},{\"line\":91,\"text\":\" {\"},{\"line\":92,\"text\":\" $this->assertPostOnly();\"},{\"line\":93,\"text\":\" $this->assertStaff(true);\"},{\"line\":94,\"text\":\"\"},{\"line\":95,\"text\":\" $ticket = $this->assertTicket();\"},{\"line\":96,\"text\":\" $newStatus = trim($this->filter('status', 'str'));\"},{\"line\":97,\"text\":\" $assignedUserId = (int)$this->filter('assigned_user_id', 'uint');\"},{\"sep\":true},{\"line\":100,\"text\":\" $staffUpdate = $this->service(StaffUpdate::class);\"},{\"line\":101,\"text\":\" $staffUpdate->validateTransition((string)$ticket->status, $newStatus);\"},{\"line\":102,\"text\":\"\"},{\"line\":103,\"text\":\" if ($assignedUserId > 0)\"},{\"line\":104,\"text\":\" {\"},{\"line\":105,\"text\":\" if (!\\\\XF::visitor()->hasPermission('gramSupport', 'assign'))\"},{\"line\":106,\"text\":\" {\"},{\"line\":107,\"text\":\" return $this->noPermission();\"},{\"line\":108,\"text\":\" }\"},{\"line\":109,\"text\":\"\"},{\"line\":110,\"text\":\" $assigned = \\\\XF::em()->find('XF:User', $assignedUserId);\"},{\"line\":111,\"text\":\" if (!$assigned\"},{\"line\":112,\"text\":\" || (!$assigned->hasPermission('gramSupport', 'viewAll')\"},{\"line\":113,\"text\":\" && !$assigned->hasPermission('gramSupport', 'manage')))\"},{\"line\":114,\"text\":\" {\"},{\"line\":115,\"text\":\" return $this->error(\\\\XF::phrase('gram_support_assignee_invalid'));\"},{\"line\":116,\"text\":\" }\"},{\"line\":117,\"text\":\" }\"},{\"line\":118,\"text\":\"\"},{\"line\":119,\"text\":\" $oldStatus = (string)$ticket->status;\"},{\"line\":120,\"text\":\" $oldAssigned = (int)$ticket->assigned_user_id;\"},{\"line\":121,\"text\":\"\"},{\"line\":122,\"text\":\" $db = \\\\XF::db();\"},{\"sep\":true},{\"line\":154,\"text\":\" {\"},{\"line\":155,\"text\":\" $db->rollback();\"},{\"line\":156,\"text\":\" throw $e;\"},{\"line\":157,\"text\":\" }\"},{\"line\":158,\"text\":\"\"},{\"line\":159,\"text\":\" (new EventDispatcher())->dispatchSafely($event, $ticket);\"},{\"line\":160,\"text\":\"\"},{\"line\":161,\"text\":\" return $this->redirect(\"},{\"line\":162,\"text\":\" $this->buildLink('support/staff/ticket', null, ['ref' => $ticket->public_ref])\"},{\"line\":163,\"text\":\" );\"},{\"line\":164,\"text\":\" }\"},{\"line\":165,\"text\":\"\"},{\"line\":166,\"text\":\" private function assertTicket()\"},{\"line\":167,\"text\":\" {\"},{\"line\":168,\"text\":\" $ticket = $this->repository('Gram\\\\Support:Ticket')\"},{\"line\":169,\"text\":\" ->findByPublicRef($this->filter('ref', 'str'));\"},{\"line\":170,\"text\":\"\"},{\"line\":171,\"text\":\" if (!$ticket)\"},{\"line\":172,\"text\":\" {\"},{\"line\":173,\"text\":\" throw $this->exception($this->notFound());\"},{\"line\":174,\"text\":\" }\"},{\"line\":175,\"text\":\"\"},{\"line\":176,\"text\":\" return $ticket;\"},{\"line\":177,\"text\":\" }\"},{\"line\":178,\"text\":\"}\"}],\"present\":true},\"Gram/Support/Pub/Controller/Support.php\":{\"basename\":\"Support.php\",\"matches\":[{\"sep\":true},{\"line\":10,\"text\":\"use Gram\\\\Support\\\\Service\\\\Ticket\\\\Creator;\"},{\"line\":11,\"text\":\"use Gram\\\\Support\\\\Service\\\\Ticket\\\\Reply;\"},{\"line\":12,\"text\":\"use Gram\\\\Support\\\\Util\\\\SiteConfig;\"},{\"line\":13,\"text\":\"use XF\\\\Mvc\\\\ParameterBag;\"},{\"line\":14,\"text\":\"\"},{\"line\":15,\"text\":\"final class Support extends \\\\XF\\\\Pub\\\\Controller\\\\AbstractController\"},{\"line\":16,\"text\":\"{\"},{\"line\":17,\"text\":\" public function actionIndex()\"},{\"line\":18,\"text\":\" {\"},{\"line\":19,\"text\":\" if (\\\\XF::visitor()->user_id)\"},{\"line\":20,\"text\":\" {\"},{\"line\":21,\"text\":\" return $this->redirect($this->buildLink('account/support'));\"},{\"line\":22,\"text\":\" }\"},{\"line\":23,\"text\":\"\"},{\"line\":24,\"text\":\" return $this->redirect($this->buildLink('support/create'));\"},{\"line\":25,\"text\":\" }\"},{\"line\":26,\"text\":\"\"},{\"line\":27,\"text\":\" public function actionCreate()\"},{\"line\":28,\"text\":\" {\"},{\"line\":29,\"text\":\" $visitor = \\\\XF::visitor();\"},{\"line\":30,\"text\":\"\"},{\"line\":31,\"text\":\" if ($visitor->user_id && !$visitor->hasPermission('gramSupport', 'create'))\"},{\"line\":32,\"text\":\" {\"},{\"line\":33,\"text\":\" return $this->noPermission();\"},{\"line\":34,\"text\":\" }\"},{\"line\":35,\"text\":\"\"},{\"line\":36,\"text\":\" if ($this->isPost())\"},{\"line\":37,\"text\":\" {\"},{\"line\":38,\"text\":\" $this->assertPostOnly();\"},{\"line\":39,\"text\":\"\"},{\"line\":40,\"text\":\" $email = $this->filter('email', 'str');\"},{\"sep\":true},{\"line\":42,\"text\":\" $subject = $this->filter('subject', 'str');\"},{\"line\":43,\"text\":\" $message = $this->filter('message', 'str');\"},{\"line\":44,\"text\":\"\"},{\"line\":45,\"text\":\" if (!$visitor->user_id)\"},{\"line\":46,\"text\":\" {\"},{\"line\":47,\"text\":\" if (!$this->captchaIsValid(true))\"},{\"line\":48,\"text\":\" {\"},{\"line\":49,\"text\":\" return $this->error(\"},{\"line\":50,\"text\":\" \\\\XF::phrase('did_not_complete_the_captcha_verification_properly')\"},{\"line\":51,\"text\":\" );\"},{\"line\":52,\"text\":\" }\"},{\"line\":53,\"text\":\"\"},{\"line\":54,\"text\":\" /** @var RateLimiter $rateLimiter */\"},{\"line\":55,\"text\":\" $rateLimiter = $this->service(RateLimiter::class);\"},{\"line\":56,\"text\":\" $allowed = $rateLimiter->consumeGuest(\"},{\"sep\":true},{\"line\":58,\"text\":\" $email,\"},{\"line\":59,\"text\":\" SiteConfig::guestRateLimitCount(),\"},{\"line\":60,\"text\":\" SiteConfig::guestRateLimitWindowSeconds()\"},{\"line\":61,\"text\":\" );\"},{\"line\":62,\"text\":\"\"},{\"line\":63,\"text\":\" if (!$allowed)\"},{\"line\":64,\"text\":\" {\"},{\"line\":65,\"text\":\" return $this->error(\\\\XF::phrase('gram_support_rate_limited'));\"},{\"line\":66,\"text\":\" }\"},{\"line\":67,\"text\":\" }\"},{\"line\":68,\"text\":\"\"},{\"line\":69,\"text\":\" $upload = $this->request->getFile('screenshot', false, false);\"},{\"line\":70,\"text\":\" $tempHash = bin2hex(random_bytes(16));\"},{\"line\":71,\"text\":\" $attachmentFlow = new GuestTicketCreateAttachmentFlow();\"},{\"line\":72,\"text\":\"\"},{\"sep\":true},{\"line\":106,\"text\":\" }\"},{\"line\":107,\"text\":\" }\"},{\"line\":108,\"text\":\"\"},{\"line\":109,\"text\":\" if ($created['guest_secret'])\"},{\"line\":110,\"text\":\" {\"},{\"line\":111,\"text\":\" $secret = (string)$created['guest_secret'];\"},{\"line\":112,\"text\":\"\"},{\"line\":113,\"text\":\" return $this->view(\"},{\"line\":114,\"text\":\" 'Gram\\\\Support:CreatedGuest',\"},{\"line\":115,\"text\":\" 'gram_support_created_guest',\"},{\"line\":116,\"text\":\" [\"},{\"line\":117,\"text\":\" 'ticket' => $ticket,\"},{\"line\":118,\"text\":\" 'accessCode' => $secret,\"},{\"line\":119,\"text\":\" 'magicLink' => $this->buildLink('canonical:support/access') . '#token=' . rawurlencode($secret)\"},{\"line\":120,\"text\":\" ]\"},{\"line\":121,\"text\":\" );\"},{\"line\":122,\"text\":\" }\"},{\"line\":123,\"text\":\"\"},{\"line\":124,\"text\":\" return $this->redirect(\"},{\"line\":125,\"text\":\" $this->buildLink('support/ticket', null, ['ref' => $ticket->public_ref])\"},{\"line\":126,\"text\":\" );\"},{\"line\":127,\"text\":\" }\"},{\"line\":128,\"text\":\"\"},{\"line\":129,\"text\":\" return $this->view(\"},{\"line\":130,\"text\":\" 'Gram\\\\Support:Create',\"},{\"line\":131,\"text\":\" 'gram_support_create',\"},{\"line\":132,\"text\":\" ['forceCaptcha' => !$visitor->user_id]\"},{\"line\":133,\"text\":\" );\"},{\"line\":134,\"text\":\" }\"},{\"line\":135,\"text\":\"\"},{\"line\":136,\"text\":\" public function actionAccess()\"},{\"line\":137,\"text\":\" {\"},{\"line\":138,\"text\":\" if ($this->isPost())\"},{\"line\":139,\"text\":\" {\"},{\"line\":140,\"text\":\" $this->assertPostOnly();\"},{\"line\":141,\"text\":\"\"},{\"line\":142,\"text\":\" $secret = trim($this->filter('access_code', 'str'));\"},{\"line\":143,\"text\":\" if ($secret === '')\"},{\"line\":144,\"text\":\" {\"},{\"line\":145,\"text\":\" return $this->error(\\\\XF::phrase('gram_support_access_code_required'));\"},{\"line\":146,\"text\":\" }\"},{\"line\":147,\"text\":\"\"},{\"line\":148,\"text\":\" $ticket = $this->repository('Gram\\\\Support:Ticket')\"},{\"line\":149,\"text\":\" ->findGuestAccessibleBySecret($secret, \\\\XF::$time);\"},{\"line\":150,\"text\":\"\"},{\"line\":151,\"text\":\" if (!$ticket)\"},{\"line\":152,\"text\":\" {\"},{\"line\":153,\"text\":\" return $this->error(\\\\XF::phrase('gram_support_access_invalid'));\"},{\"line\":154,\"text\":\" }\"},{\"line\":155,\"text\":\"\"},{\"line\":156,\"text\":\" GuestTicketSession::grant($ticket);\"},{\"line\":157,\"text\":\"\"},{\"line\":158,\"text\":\" return $this->redirect(\"},{\"line\":159,\"text\":\" $this->buildLink('support/ticket', null, ['ref' => $ticket->public_ref])\"},{\"line\":160,\"text\":\" );\"},{\"line\":161,\"text\":\" }\"},{\"line\":162,\"text\":\"\"},{\"line\":163,\"text\":\" return $this->view(\"},{\"line\":164,\"text\":\" 'Gram\\\\Support:Access',\"},{\"line\":165,\"text\":\" 'gram_support_access',\"},{\"line\":166,\"text\":\" []\"},{\"line\":167,\"text\":\" );\"},{\"line\":168,\"text\":\" }\"},{\"line\":169,\"text\":\"\"},{\"line\":170,\"text\":\" public function actionTicket()\"},{\"line\":171,\"text\":\" {\"},{\"line\":172,\"text\":\" $ticket = $this->assertViewableTicketByRef($this->filter('ref', 'str'));\"},{\"line\":173,\"text\":\"\"},{\"line\":174,\"text\":\" $messages = $this->repository('Gram\\\\Support:Message')\"},{\"line\":175,\"text\":\" ->findPublicForTicket((int)$ticket->ticket_id)\"},{\"line\":176,\"text\":\" ->fetch();\"},{\"line\":177,\"text\":\"\"},{\"line\":178,\"text\":\" return $this->view(\"},{\"line\":179,\"text\":\" 'Gram\\\\Support:Ticket',\"},{\"line\":180,\"text\":\" 'gram_support_ticket',\"},{\"line\":181,\"text\":\" [\"},{\"line\":182,\"text\":\" 'ticket' => $ticket,\"},{\"line\":183,\"text\":\" 'messages' => $messages\"},{\"line\":184,\"text\":\" ]\"},{\"line\":185,\"text\":\" );\"},{\"line\":186,\"text\":\" }\"},{\"line\":187,\"text\":\"\"},{\"line\":188,\"text\":\" public function actionReply()\"},{\"line\":189,\"text\":\" {\"},{\"line\":190,\"text\":\" $this->assertPostOnly();\"},{\"line\":191,\"text\":\"\"},{\"line\":192,\"text\":\" $ticket = $this->assertViewableTicketByRef($this->filter('ref', 'str'));\"},{\"line\":193,\"text\":\" $visitor = \\\\XF::visitor();\"},{\"line\":194,\"text\":\"\"},{\"line\":195,\"text\":\" if ($visitor->user_id)\"},{\"line\":196,\"text\":\" {\"},{\"line\":197,\"text\":\" if ((int)$ticket->user_id !== (int)$visitor->user_id\"},{\"line\":198,\"text\":\" || !$visitor->hasPermission('gramSupport', 'replyOwn'))\"},{\"line\":199,\"text\":\" {\"},{\"line\":200,\"text\":\" return $this->noPermission();\"},{\"line\":201,\"text\":\" }\"},{\"line\":202,\"text\":\" }\"},{\"line\":203,\"text\":\" elseif (!GuestTicketSession::hasGrant($ticket))\"},{\"line\":204,\"text\":\" {\"},{\"line\":205,\"text\":\" return $this->noPermission();\"},{\"line\":206,\"text\":\" }\"},{\"line\":207,\"text\":\"\"},{\"line\":208,\"text\":\" $message = $this->filter('message', 'str');\"},{\"line\":209,\"text\":\"\"},{\"line\":210,\"text\":\" /** @var Reply $reply */\"},{\"line\":211,\"text\":\" $reply = $this->service(Reply::class);\"},{\"line\":212,\"text\":\" $reply->add($ticket, $message, false, false);\"},{\"line\":213,\"text\":\"\"},{\"line\":214,\"text\":\" return $this->redirect(\"},{\"line\":215,\"text\":\" $this->buildLink('support/ticket', null, ['ref' => $ticket->public_ref])\"},{\"line\":216,\"text\":\" );\"},{\"line\":217,\"text\":\" }\"},{\"line\":218,\"text\":\"\"},{\"line\":219,\"text\":\" private function assertViewableTicketByRef(string $publicRef)\"},{\"line\":220,\"text\":\" {\"}],\"present\":true},\"XF/Http/Response.php\":{\"basename\":\"Response.php\",\"matches\":[{\"sep\":true},{\"line\":240,\"text\":\"\\t\\treturn $name;\"},{\"line\":241,\"text\":\"\\t}\"},{\"line\":242,\"text\":\"\"},{\"line\":243,\"text\":\"\\tpublic function body($body = null)\"},{\"line\":244,\"text\":\"\\t{\"},{\"line\":245,\"text\":\"\\t\\tif ($body === null)\"},{\"line\":246,\"text\":\"\\t\\t{\"},{\"line\":247,\"text\":\"\\t\\t\\treturn $this->body;\"},{\"line\":248,\"text\":\"\\t\\t}\"},{\"line\":249,\"text\":\"\"},{\"line\":250,\"text\":\"\\t\\t$this->body = $body;\"},{\"line\":251,\"text\":\"\"},{\"line\":252,\"text\":\"\\t\\treturn $this;\"},{\"line\":253,\"text\":\"\\t}\"},{\"line\":254,\"text\":\"\"},{\"line\":255,\"text\":\"\\tpublic function responseFile($fileName)\"},{\"line\":256,\"text\":\"\\t{\"},{\"line\":257,\"text\":\"\\t\\treturn new ResponseFile($fileName);\"},{\"sep\":true},{\"line\":282,\"text\":\"\\t\\t}\"},{\"line\":283,\"text\":\"\"},{\"line\":284,\"text\":\"\\t\\t$this->includeContentLength = (bool) $use;\"},{\"line\":285,\"text\":\"\"},{\"line\":286,\"text\":\"\\t\\treturn $this;\"},{\"line\":287,\"text\":\"\\t}\"},{\"line\":288,\"text\":\"\"},{\"line\":289,\"text\":\"\\tpublic function send(?Request $request = null)\"},{\"line\":290,\"text\":\"\\t{\"},{\"line\":291,\"text\":\"\\t\\t$this->prepareForOutput($request);\"},{\"line\":292,\"text\":\"\\t\\t$this->sendHeaders();\"},{\"line\":293,\"text\":\"\\t\\t$this->sendBody();\"},{\"line\":294,\"text\":\"\\t}\"},{\"line\":295,\"text\":\"\"},{\"line\":296,\"text\":\"\\tpublic function prepareForOutput(?Request $request = null)\"},{\"sep\":true},{\"line\":381,\"text\":\"\\tpublic function removeCookie($name)\"},{\"line\":382,\"text\":\"\\t{\"},{\"line\":383,\"text\":\"\\t\\tunset($this->cookies[$name]);\"},{\"line\":384,\"text\":\"\"},{\"line\":385,\"text\":\"\\t\\treturn $this;\"},{\"line\":386,\"text\":\"\\t}\"},{\"line\":387,\"text\":\"\"},{\"line\":388,\"text\":\"\\tpublic function sendHeaders()\"},{\"line\":389,\"text\":\"\\t{\"},{\"line\":390,\"text\":\"\\t\\tforeach ($this->headers AS $key => $value)\"},{\"line\":391,\"text\":\"\\t\\t{\"},{\"line\":392,\"text\":\"\\t\\t\\tif (is_array($value))\"},{\"line\":393,\"text\":\"\\t\\t\\t{\"},{\"line\":394,\"text\":\"\\t\\t\\t\\tforeach ($value AS $innerValue)\"},{\"line\":395,\"text\":\"\\t\\t\\t\\t{\"},{\"sep\":true},{\"line\":446,\"text\":\"\\t\\t\\t\\t}\"},{\"line\":447,\"text\":\"\"},{\"line\":448,\"text\":\"\\t\\t\\t\\tcall_user_func('setcookie', $name, $value, $options);\"},{\"line\":449,\"text\":\"\\t\\t\\t}\"},{\"line\":450,\"text\":\"\\t\\t}\"},{\"line\":451,\"text\":\"\\t}\"},{\"line\":452,\"text\":\"\"},{\"line\":453,\"text\":\"\\tpublic function sendBody()\"},{\"line\":454,\"text\":\"\\t{\"},{\"line\":455,\"text\":\"\\t\\tif ($this->body instanceof ResponseFile)\"},{\"line\":456,\"text\":\"\\t\\t{\"},{\"line\":457,\"text\":\"\\t\\t\\tif ($this->includeContentLength)\"},{\"line\":458,\"text\":\"\\t\\t\\t{\"},{\"line\":459,\"text\":\"\\t\\t\\t\\theader('Content-Length: ' . $this->body->getLength());\"},{\"line\":460,\"text\":\"\\t\\t\\t}\"},{\"line\":461,\"text\":\"\"},{\"line\":462,\"text\":\"\\t\\t\\t$this->body->output();\"},{\"line\":463,\"text\":\"\\t\\t}\"},{\"line\":464,\"text\":\"\\t\\telse if ($this->body instanceof ResponseStream)\"},{\"line\":465,\"text\":\"\\t\\t{\"},{\"line\":466,\"text\":\"\\t\\t\\tif ($this->includeContentLength)\"},{\"line\":467,\"text\":\"\\t\\t\\t{\"},{\"line\":468,\"text\":\"\\t\\t\\t\\t$length = $this->body->getLength();\"},{\"line\":469,\"text\":\"\\t\\t\\t\\tif ($length !== null)\"},{\"line\":470,\"text\":\"\\t\\t\\t\\t{\"},{\"line\":471,\"text\":\"\\t\\t\\t\\t\\theader('Content-Length: ' . $length);\"},{\"line\":472,\"text\":\"\\t\\t\\t\\t}\"},{\"line\":473,\"text\":\"\\t\\t\\t}\"},{\"line\":474,\"text\":\"\"},{\"line\":475,\"text\":\"\\t\\t\\t$this->body->output();\"},{\"line\":476,\"text\":\"\\t\\t}\"},{\"line\":477,\"text\":\"\\t\\telse\"},{\"line\":478,\"text\":\"\\t\\t{\"},{\"line\":479,\"text\":\"\\t\\t\\tif ($this->compress)\"},{\"line\":480,\"text\":\"\\t\\t\\t{\"},{\"line\":481,\"text\":\"\\t\\t\\t\\t$toPrint = gzencode($this->body, 9);\"},{\"line\":482,\"text\":\"\\t\\t\\t}\"},{\"line\":483,\"text\":\"\\t\\t\\telse\"},{\"line\":484,\"text\":\"\\t\\t\\t{\"},{\"line\":485,\"text\":\"\\t\\t\\t\\t$toPrint = $this->body;\"},{\"line\":486,\"text\":\"\\t\\t\\t}\"},{\"line\":487,\"text\":\"\"},{\"line\":488,\"text\":\"\\t\\t\\tif ($this->includeContentLength)\"},{\"line\":489,\"text\":\"\\t\\t\\t{\"},{\"line\":490,\"text\":\"\\t\\t\\t\\theader('Content-Length: ' . strlen($toPrint));\"},{\"line\":491,\"text\":\"\\t\\t\\t}\"},{\"line\":492,\"text\":\"\"},{\"line\":493,\"text\":\"\\t\\t\\techo $toPrint;\"},{\"line\":494,\"text\":\"\\t\\t}\"},{\"line\":495,\"text\":\"\\t}\"},{\"line\":496,\"text\":\"\"},{\"line\":497,\"text\":\"\\tpublic function contentIsCompressible(Request $request)\"},{\"line\":498,\"text\":\"\\t{\"},{\"line\":499,\"text\":\"\\t\\tif (\"},{\"line\":500,\"text\":\"\\t\\t\\t!is_string($this->body)\"},{\"line\":501,\"text\":\"\\t\\t\\t|| !preg_match('#^(?:text/|application/(?:json|xml|rss\\\\+xml)$)#i', $this->contentType)\"},{\"line\":502,\"text\":\"\\t\\t\\t|| strpos($request->getServer('HTTP_ACCEPT_ENCODING', ''), 'gzip') === false\"},{\"line\":503,\"text\":\"\\t\\t)\"},{\"line\":504,\"text\":\"\\t\\t{\"},{\"line\":505,\"text\":\"\\t\\t\\treturn false;\"},{\"line\":506,\"text\":\"\\t\\t}\"},{\"line\":507,\"text\":\"\"},{\"line\":508,\"text\":\"\\t\\tif (!function_exists('gzencode'))\"},{\"line\":509,\"text\":\"\\t\\t{\"},{\"line\":510,\"text\":\"\\t\\t\\treturn false;\"},{\"line\":511,\"text\":\"\\t\\t}\"},{\"line\":512,\"text\":\"\"},{\"line\":513,\"text\":\"\\t\\treturn (strlen($this->body) >= 20);\"},{\"line\":514,\"text\":\"\\t}\"},{\"line\":515,\"text\":\"}\"}],\"present\":true}}},\"guest_stderr_present\":false,\"inner_rc\":0,\"ok\":true,\"out_truncated\":false,\"transport_rc\":0,\"transport_stderr_bytes\":0,\"transport_stderr_sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"}\nGRAM516R5RCA3_DECISION=PASS_ERROR_REQUESTSTATE_AND_SOURCE_CAPTURED\nGRAM516R5RCA3_NEXT_GATE=CLASSIFY_CURRENT_RUNTIME_DEFECT\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260918-GRAM-SUPPORT-CODEVIPE-ERROR-REQUESTSTATE-RCA-READONLY-516R5RCA3\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n"
+ "output": "GRAM516R5RCA4_SAFE_REPORT={\"err_truncated\":false,\"guest\":{\"core\":[{\"matches\":[{\"sep\":true},{\"line\":125,\"text\":\"\\t\\tswitch (get_class($reply))\"},{\"line\":126,\"text\":\"\\t\\t{\"},{\"line\":127,\"text\":\"\\t\\t\\tcase Redirect::class:\"},{\"line\":128,\"text\":\"\\t\\t\\tcase Reroute::class:\"},{\"line\":129,\"text\":\"\\t\\t\\t\\treturn false; // don't update anything, assume the next page will do it\"},{\"line\":130,\"text\":\"\"},{\"line\":131,\"text\":\"\\t\\t\\tcase Message::class:\"},{\"line\":132,\"text\":\"\\t\\t\\tcase View::class:\"},{\"line\":133,\"text\":\"\\t\\t\\t\\t$viewState = 'valid';\"},{\"line\":134,\"text\":\"\\t\\t\\t\\tbreak;\"},{\"line\":135,\"text\":\"\\t\\t}\"},{\"line\":136,\"text\":\"\"},{\"line\":137,\"text\":\"\\t\\tif ($reply->getResponseCode() >= 400)\"},{\"line\":138,\"text\":\"\\t\\t{\"},{\"line\":139,\"text\":\"\\t\\t\\t$viewState = 'error';\"},{\"line\":140,\"text\":\"\\t\\t}\"},{\"line\":141,\"text\":\"\"},{\"line\":142,\"text\":\"\\t\\treturn true;\"},{\"line\":143,\"text\":\"\\t}\"},{\"line\":144,\"text\":\"\"},{\"line\":145,\"text\":\"\\tpublic function checkTfaRedirect()\"},{\"line\":146,\"text\":\"\\t{\"},{\"line\":147,\"text\":\"\\t\\t$session = $this->session();\"},{\"line\":148,\"text\":\"\\t\\tif ($session->tfaLoginRedirect)\"},{\"line\":149,\"text\":\"\\t\\t{\"},{\"sep\":true},{\"line\":219,\"text\":\"\\tpublic function assertNotDisabled($action)\"},{\"line\":220,\"text\":\"\\t{\"},{\"line\":221,\"text\":\"\\t\\tif (\\\\XF::visitor()->user_state == 'disabled')\"},{\"line\":222,\"text\":\"\\t\\t{\"},{\"line\":223,\"text\":\"\\t\\t\\tthrow $this->exception(\"},{\"line\":224,\"text\":\"\\t\\t\\t\\t$this->plugin(ErrorPlugin::class)->actionDisabled()\"},{\"line\":225,\"text\":\"\\t\\t\\t);\"},{\"line\":226,\"text\":\"\\t\\t}\"},{\"line\":227,\"text\":\"\\t}\"},{\"line\":228,\"text\":\"\"},{\"line\":229,\"text\":\"\\tpublic function assertCanonicalBaseUrl($action)\"},{\"line\":230,\"text\":\"\\t{\"},{\"line\":231,\"text\":\"\\t\\tif ($this->responseType != 'html')\"},{\"line\":232,\"text\":\"\\t\\t{\"},{\"line\":233,\"text\":\"\\t\\t\\treturn;\"},{\"line\":234,\"text\":\"\\t\\t}\"},{\"line\":235,\"text\":\"\"},{\"line\":236,\"text\":\"\\t\\tif (!$this->request->isGet() && !$this->request->isHead())\"},{\"line\":237,\"text\":\"\\t\\t{\"},{\"line\":238,\"text\":\"\\t\\t\\treturn;\"},{\"line\":239,\"text\":\"\\t\\t}\"},{\"line\":240,\"text\":\"\"},{\"line\":241,\"text\":\"\\t\\t$options = $this->options();\"},{\"line\":242,\"text\":\"\\t\\tif (!$options->boardUrlCanonical)\"},{\"line\":243,\"text\":\"\\t\\t{\"},{\"sep\":true},{\"line\":273,\"text\":\"\"},{\"line\":274,\"text\":\"\\t\\t\\tthrow $this->exception($reply);\"},{\"line\":275,\"text\":\"\\t\\t}\"},{\"line\":276,\"text\":\"\\t}\"},{\"line\":277,\"text\":\"\"},{\"line\":278,\"text\":\"\\tpublic function assertBoardActive($action)\"},{\"line\":279,\"text\":\"\\t{\"},{\"line\":280,\"text\":\"\\t\\t$options = $this->options();\"},{\"line\":281,\"text\":\"\\t\\tif (!$options->boardActive && !\\\\XF::visitor()->is_admin)\"},{\"line\":282,\"text\":\"\\t\\t{\"},{\"line\":283,\"text\":\"\\t\\t\\t$reply = $this->message(new PreEscaped($options->boardInactiveMessage), $this->app->config('serviceUnavailableCode'));\"},{\"line\":284,\"text\":\"\\t\\t\\t$reply->setPageParam('skipSidebarWidgets', true);\"},{\"line\":285,\"text\":\"\\t\\t\\t$reply->setResponseHeader('Retry-After', 60);\"},{\"line\":286,\"text\":\"\\t\\t\\t$reply->setResponseHeader('Refresh', 60);\"},{\"line\":287,\"text\":\"\"},{\"line\":288,\"text\":\"\\t\\t\\tthrow $this->exception($reply);\"},{\"line\":289,\"text\":\"\\t\\t}\"},{\"line\":290,\"text\":\"\\t}\"},{\"line\":291,\"text\":\"\"},{\"line\":292,\"text\":\"\\tpublic function assertTfaRequirement($action)\"},{\"line\":293,\"text\":\"\\t{\"},{\"line\":294,\"text\":\"\\t\\t$visitor = \\\\XF::visitor();\"},{\"line\":295,\"text\":\"\\t\\tif ($visitor->user_id\"},{\"line\":296,\"text\":\"\\t\\t\\t&& empty($visitor->Option->use_tfa)\"},{\"line\":297,\"text\":\"\\t\\t\\t&& \\\\XF::config('enableTfa')\"},{\"line\":298,\"text\":\"\\t\\t\\t&& $visitor->hasPermission('general', 'requireTfa')\"},{\"sep\":true},{\"line\":459,\"text\":\"\\t\\treturn in_array($requestRoutePath, $whitelistRoutePaths, true);\"},{\"line\":460,\"text\":\"\\t}\"},{\"line\":461,\"text\":\"\"},{\"line\":462,\"text\":\"\\tpublic function isEmbeddedImageRequest(): bool\"},{\"line\":463,\"text\":\"\\t{\"},{\"line\":464,\"text\":\"\\t\\treturn $this->request->isEmbeddedImageRequest();\"},{\"line\":465,\"text\":\"\\t}\"},{\"line\":466,\"text\":\"\"},{\"line\":467,\"text\":\"\\tpublic function assertNotEmbeddedImageRequest()\"},{\"line\":468,\"text\":\"\\t{\"},{\"line\":469,\"text\":\"\\t\\tif ($this->isEmbeddedImageRequest())\"},{\"line\":470,\"text\":\"\\t\\t{\"},{\"line\":471,\"text\":\"\\t\\t\\t$this->setResponseType('raw');\"},{\"line\":472,\"text\":\"\"},{\"line\":473,\"text\":\"\\t\\t\\t$view = $this->view('XF:Error\\\\EmbeddedImageRequest');\"},{\"line\":474,\"text\":\"\\t\\t\\t$view->setResponseCode(406);\"},{\"line\":475,\"text\":\"\"},{\"line\":476,\"text\":\"\\t\\t\\tthrow $this->exception($view);\"},{\"line\":477,\"text\":\"\\t\\t}\"},{\"line\":478,\"text\":\"\\t}\"},{\"line\":479,\"text\":\"\"},{\"line\":480,\"text\":\"\\tpublic function hasContentPendingApproval()\"},{\"line\":481,\"text\":\"\\t{\"},{\"line\":482,\"text\":\"\\t\\t$pendingUntil = $this->session()->hasContentPendingUntil;\"},{\"line\":483,\"text\":\"\\t\\treturn ($pendingUntil && $pendingUntil >= \\\\XF::$time);\"},{\"line\":484,\"text\":\"\\t}\"},{\"line\":485,\"text\":\"\"},{\"line\":486,\"text\":\"\\tprotected function isDiscouraged()\"},{\"sep\":true},{\"line\":565,\"text\":\"\\tpublic function assertNotFlooding($action, $floodingLimit = null)\"},{\"line\":566,\"text\":\"\\t{\"},{\"line\":567,\"text\":\"\\t\\t$visitor = \\\\XF::visitor();\"},{\"line\":568,\"text\":\"\\t\\tif ($visitor->hasPermission('general', 'bypassFloodCheck'))\"},{\"line\":569,\"text\":\"\\t\\t{\"},{\"line\":570,\"text\":\"\\t\\t\\treturn;\"},{\"line\":571,\"text\":\"\\t\\t}\"},{\"line\":572,\"text\":\"\"},{\"line\":573,\"text\":\"\\t\\t$floodChecker = $this->service(FloodCheckService::class);\"},{\"line\":574,\"text\":\"\\t\\t$timeRemaining = $floodChecker->checkFlooding($action, $visitor->user_id, $floodingLimit);\"},{\"line\":575,\"text\":\"\\t\\tif ($timeRemaining)\"},{\"line\":576,\"text\":\"\\t\\t{\"},{\"line\":577,\"text\":\"\\t\\t\\tthrow $this->exception($this->responseFlooding($timeRemaining));\"},{\"line\":578,\"text\":\"\\t\\t}\"},{\"line\":579,\"text\":\"\\t}\"},{\"line\":580,\"text\":\"\"},{\"line\":581,\"text\":\"\\tpublic function responseFlooding($floodSeconds)\"},{\"line\":582,\"text\":\"\\t{\"},{\"line\":583,\"text\":\"\\t\\treturn $this->error(\\\\XF::phrase('must_wait_x_seconds_before_performing_this_action', ['count' => $floodSeconds]));\"},{\"line\":584,\"text\":\"\\t}\"},{\"line\":585,\"text\":\"\"},{\"line\":586,\"text\":\"\\tpublic function isRobot()\"},{\"line\":587,\"text\":\"\\t{\"},{\"line\":588,\"text\":\"\\t\\treturn boolval($this->request->getRobotName());\"},{\"line\":589,\"text\":\"\\t}\"},{\"line\":590,\"text\":\"\"},{\"line\":591,\"text\":\"\\t/**\"},{\"line\":592,\"text\":\"\\t * @return IpRepository\"},{\"line\":593,\"text\":\"\\t */\"}],\"path\":\"src/XF/Pub/Controller/AbstractController.php\",\"present\":true,\"sha256\":\"023efffff88cd1675173f30a8104d25fb220a5d8dc989d89c33d3ba09b0c0169\"}],\"error\":null,\"files\":[{\"matches\":[],\"path\":\"Pub/Controller/Support.php\",\"present\":true,\"sha256\":\"6cb34b1d27e9f0132263637cefa62fe0e998a9a86620b7ac33199f41ee86f9d4\"},{\"matches\":[],\"path\":\"Pub/Controller/StaffSupport.php\",\"present\":true,\"sha256\":\"6852bd0061d6e118851673bfd4099e2b22e6291bf09f429820740844996f93f9\"},{\"matches\":[{\"sep\":true},{\"line\":1,\"text\":\"\"},{\"line\":2,\"text\":\"\"},{\"line\":3,\"text\":\" \"},{\"line\":4,\"text\":\" \"},{\"line\":5,\"text\":\" \"},{\"line\":6,\"text\":\" \"},{\"line\":7,\"text\":\"\"}],\"path\":\"_data/routes.xml\",\"present\":true,\"sha256\":\"c80e6b0f7153993915d8bbc8ee6b36e6386b00bb1865d6aff050f9c1fd1f0302\"},{\"matches\":[{\"sep\":true},{\"line\":553,\"text\":\"<xf:if is=\\\"$xf.options.gramSupportSiteId\\\">\"},{\"line\":554,\"text\":\"\\t<a class=\\\"gramSupport-launcher button button--primary\\\"\"},{\"line\":555,\"text\":\"\\t\\thref=\\\"{{ link('support/create') }}\\\"\"},{\"line\":556,\"text\":\"\\t\\taria-label=\\\"{{ phrase('gram_support_open_support') }}\\\">\"},{\"line\":557,\"text\":\"\\t\\t{{ phrase('gram_support_open_support') }}\"},{\"line\":558,\"text\":\"\\t</a>\"},{\"line\":559,\"text\":\"</xf:if>\"},{\"line\":560,\"text\":\"\"},{\"line\":561,\"text\":\" <xf:title>{{ phrase('gram_support_staff_queue') }}</xf:title>\"},{\"line\":562,\"text\":\"<xf:css src=\\\"gram_support.less\\\" />\"},{\"line\":563,\"text\":\"<span class=\\\"js-gramSupportPwaConfig\\\" hidden\"},{\"line\":564,\"text\":\"\\tdata-manifest-url=\\\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\\\"\"},{\"line\":565,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"></span>\"},{\"line\":566,\"text\":\"<xf:js addon=\\\"Gram/Support\\\" src=\\\"gram/support/staff-pwa.js\\\" min=\\\"1\\\" />\"},{\"line\":567,\"text\":\"\"},{\"line\":568,\"text\":\"<div class=\\\"block\\\">\"},{\"line\":569,\"text\":\"\\t<div class=\\\"block-container\\\">\"},{\"line\":570,\"text\":\"\\t\\t<div class=\\\"block-body\\\">\"},{\"line\":571,\"text\":\"\\t\\t\\t<xf:foreach loop=\\\"$tickets\\\" value=\\\"$ticket\\\">\"},{\"line\":572,\"text\":\"\\t\\t\\t\\t<div class=\\\"block-row\\\">\"},{\"line\":573,\"text\":\"\\t\\t\\t\\t\\t<a href=\\\"{{ link('support/staff/ticket', null, {'ref': $ticket.public_ref}) }}\\\">\"},{\"line\":574,\"text\":\"\\t\\t\\t\\t\\t\\t{{ $ticket.public_ref }} \\u2014 {{ $ticket.subject }}\"},{\"line\":575,\"text\":\"\\t\\t\\t\\t\\t</a>\"},{\"line\":576,\"text\":\"\\t\\t\\t\\t\\t<span class=\\\"u-muted\\\">\"},{\"line\":577,\"text\":\"<xf:if is=\\\"$ticket.status == 'NEW'\\\">\\u041d\\u043e\\u0432\\u044b\\u0439\"},{\"sep\":true},{\"line\":579,\"text\":\"<xf:elseif is=\\\"$ticket.status == 'WAITING_USER'\\\" />\\u041e\\u0436\\u0438\\u0434\\u0430\\u0435\\u0442 \\u043e\\u0442\\u0432\\u0435\\u0442\\u0430 \\u043f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044f\"},{\"line\":580,\"text\":\"<xf:elseif is=\\\"$ticket.status == 'RESOLVED'\\\" />\\u0420\\u0435\\u0448\\u0451\\u043d\"},{\"line\":581,\"text\":\"<xf:elseif is=\\\"$ticket.status == 'CLOSED'\\\" />\\u0417\\u0430\\u043a\\u0440\\u044b\\u0442\"},{\"line\":582,\"text\":\"<xf:else />{{ $ticket.status }}\"},{\"line\":583,\"text\":\"</xf:if>\"},{\"line\":584,\"text\":\"</span>\"},{\"line\":585,\"text\":\"\\t\\t\\t\\t</div>\"},{\"line\":586,\"text\":\"\\t\\t\\t</xf:foreach>\"},{\"line\":587,\"text\":\"\\t\\t</div>\"},{\"line\":588,\"text\":\"\\t</div>\"},{\"line\":589,\"text\":\"</div>\"},{\"line\":590,\"text\":\"\"},{\"line\":591,\"text\":\" 'use strict';\"},{\"line\":592,\"text\":\"\"},{\"line\":593,\"text\":\"const OFFLINE_URL = '{{ base_url('js/gram/support/pwa/offline.html')|escape('js') }}';\"},{\"line\":594,\"text\":\"const STATIC_CACHE = 'gram-support-staff-static-v1';\"},{\"line\":595,\"text\":\"\"},{\"line\":596,\"text\":\"self.addEventListener('install', event => {\"},{\"line\":597,\"text\":\"\\tevent.waitUntil(\"},{\"line\":598,\"text\":\"\\t\\tcaches.open(STATIC_CACHE)\"},{\"line\":599,\"text\":\"\\t\\t\\t.then(cache => cache.addAll([OFFLINE_URL]))\"},{\"line\":600,\"text\":\"\\t\\t\\t.then(() => self.skipWaiting())\"},{\"line\":601,\"text\":\"\\t);\"},{\"line\":602,\"text\":\"});\"},{\"line\":603,\"text\":\"\"},{\"sep\":true},{\"line\":655,\"text\":\"\\t\\t\\t\\t\\treturn response;\"},{\"line\":656,\"text\":\"\\t\\t\\t\\t});\"},{\"line\":657,\"text\":\"\\t\\t\\t\\treturn cached || network;\"},{\"line\":658,\"text\":\"\\t\\t\\t})\"},{\"line\":659,\"text\":\"\\t\\t)\"},{\"line\":660,\"text\":\"\\t);\"},{\"line\":661,\"text\":\"});\"},{\"line\":662,\"text\":\"\"},{\"line\":663,\"text\":\" <xf:title>{{ phrase('gram_support_staff_ticket') }} {{ $ticket.public_ref }}</xf:title>\"},{\"line\":664,\"text\":\"<xf:css src=\\\"gram_support.less\\\" />\"},{\"line\":665,\"text\":\"<span class=\\\"js-gramSupportPwaConfig\\\" hidden\"},{\"line\":666,\"text\":\"\\tdata-manifest-url=\\\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\\\"\"},{\"line\":667,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"></span>\"},{\"line\":668,\"text\":\"<xf:js addon=\\\"Gram/Support\\\" src=\\\"gram/support/staff-pwa.js\\\" min=\\\"1\\\" />\"},{\"line\":669,\"text\":\"\"},{\"line\":670,\"text\":\"<div class=\\\"block\\\">\"},{\"line\":671,\"text\":\"\\t<div class=\\\"block-container\\\">\"},{\"line\":672,\"text\":\"\\t\\t<h2 class=\\\"block-header\\\">{{ $ticket.public_ref }} \\u2014 {{ $ticket.subject }}</h2>\"},{\"line\":673,\"text\":\"\\t\\t<div class=\\\"block-body\\\">\"},{\"line\":674,\"text\":\"\\t\\t\\t<xf:foreach loop=\\\"$messages\\\" value=\\\"$message\\\">\"},{\"line\":675,\"text\":\"\\t\\t\\t\\t<div class=\\\"block-row {{ $message.is_internal ? 'gramSupport-message--internal' : '' }}\\\">\"},{\"line\":676,\"text\":\"\\t\\t\\t\\t\\t<div class=\\\"gramSupport-messageMeta\\\">\"},{\"line\":677,\"text\":\"\\t\\t\\t\\t\\t\\t{{ date_time($message.message_date) }}\"},{\"line\":678,\"text\":\"\\t\\t\\t\\t\\t\\t<xf:if is=\\\"$message.is_internal\\\"> \\u00b7 {{ phrase('gram_support_internal_note') }}</xf:if>\"},{\"line\":679,\"text\":\"\\t\\t\\t\\t\\t</div>\"}],\"path\":\"_data/templates.xml\",\"present\":true,\"sha256\":\"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239\"},{\"matches\":[],\"path\":\"addon.json\",\"present\":true,\"sha256\":\"566f1739937088517f5ef0dd2d20bc92460084028180c16502931fa86057aea5\"}],\"occurrences\":[{\"hit_count\":2,\"hits\":[{\"line\":25,\"text\":\" 'Gram\\\\Support:PwaServiceWorker',\"},{\"line\":26,\"text\":\" 'gram_support_staff_service_worker',\"}],\"path\":\"Pub/Controller/Pwa.php\",\"sha256\":\"9e3217d9524349a8137b89d418e4693ca17f8e5f61ba5b563fff747d1014efb3\"},{\"hit_count\":2,\"hits\":[{\"line\":5,\"text\":\"class PwaServiceWorker extends \\\\XF\\\\Mvc\\\\View\"},{\"line\":12,\"text\":\" 'public:gram_support_staff_service_worker',\"}],\"path\":\"Pub/View/PwaServiceWorker.php\",\"sha256\":\"700f01f005b818d63267e70dac7669a606c78fabbef5d3e01731c49db3d0be04\"},{\"hit_count\":1,\"hits\":[{\"line\":6,\"text\":\" \"}],\"path\":\"_data/routes.xml\",\"sha256\":\"c80e6b0f7153993915d8bbc8ee6b36e6386b00bb1865d6aff050f9c1fd1f0302\"},{\"hit_count\":3,\"hits\":[{\"line\":565,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"></span>\"},{\"line\":591,\"text\":\" 'use strict';\"},{\"line\":667,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"></span>\"}],\"path\":\"_data/templates.xml\",\"sha256\":\"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239\"},{\"hit_count\":1,\"hits\":[{\"line\":30,\"text\":\" \\\"src/addons/Gram/Support/Pub/View/PwaServiceWorker.php\\\": \\\"700f01f005b818d63267e70dac7669a606c78fabbef5d3e01731c49db3d0be04\\\",\"}],\"path\":\"hashes.json\",\"sha256\":\"1f947a585ee5d5936c6d1c73a7d4602c0f77ceafd98936df74b89a6a4538921f\"}],\"ok\":true},\"guest_stderr_present\":false,\"inner_rc\":0,\"ok\":true,\"out_truncated\":false,\"transport_rc\":0,\"transport_stderr_bytes\":0,\"transport_stderr_sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"}\nGRAM516R5RCA4_DECISION=PASS_SERVICE_WORKER_SOURCE_EVIDENCE_CAPTURED\nGRAM516R5RCA4_NEXT_GATE=BUILD_EXACT_SERVICE_WORKER_FIX\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n"
}
diff --git a/runtime/latest.txt b/runtime/latest.txt
index 4091590c..2ce947a5 100644
--- a/runtime/latest.txt
+++ b/runtime/latest.txt
@@ -1,15 +1,15 @@
CHAT_OUTPUT_BEGIN
-COMMAND_ID=SUPPORT-260918-GRAM-SUPPORT-CODEVIPE-ERROR-REQUESTSTATE-RCA-READONLY-516R5RCA3
+COMMAND_ID=SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4
STATUS=OK
RC=0
HOST=pve01
MODE=read-only
-COMPONENT=gram-support-codevipe-error-requeststate-rca-readonly
+COMPONENT=gram-support-service-worker-source-rca-readonly
REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
-COMMAND_SHA256=af3e7b5d91ef4c593cbdf0d032ab8022f0bfb2da04c29aafb6bd450f1e99caf7
+COMMAND_SHA256=628189b0b18497cabb62b75d0fb6506209677e28954b6201c862bba85c776534
DUPLICATE_FAILED_COMMAND_BLOCKED=false
EXECUTION_STARTED=true
CHANGE_DECLARED=false
@@ -24,13 +24,13 @@ MUTATION_OUTCOME=NO_MUTATION
SANITIZED=yes
SECRETS_INCLUDED=no
PRIVATE_ADDRESSES_INCLUDED=no
-RAW_EVIDENCE_SHA256=7de025dbfa44e4f0c49d03b4428121cbefb1c0b7b624db402a0f60b938a6ec98
-SANITIZED_OUTPUT_SHA256=7de025dbfa44e4f0c49d03b4428121cbefb1c0b7b624db402a0f60b938a6ec98
+RAW_EVIDENCE_SHA256=9742e5b94ef98a5dfa64fc2efe1dfef47880eaffad20efdf2bf9b72b47f7b6d6
+SANITIZED_OUTPUT_SHA256=9742e5b94ef98a5dfa64fc2efe1dfef47880eaffad20efdf2bf9b72b47f7b6d6
OUTPUT_BEGIN
-GRAM516R5RCA3_SAFE_REPORT={"err_truncated":false,"guest":{"error":null,"ok":true,"php_rc":0,"php_stderr_bytes":0,"php_stderr_sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","runtime":{"error":null,"error_count":4,"error_max":4,"ok":true,"rows":[{"error_id":4,"exception_type":"TypeError","filename_basename":"Response.php","line":490,"message":"strlen(): Argument #1 ($string) must be of type string, XF\\Http\\Response given","request_state":{"bytes":160,"collection_keys":{"_GET":["/support/service-worker"],"_POST":[]},"fields":{"referrer":{"host":"codevipe.ru","path":"/support/staff/ticket"},"url":{"host":null,"path":"/support/service-worker"}},"format":"json","sha256":"bf0540e9fdbe13a7e735692f32f0ebe88e3d872ce50068b9165a7546eef32fdf","top_keys":["url","referrer","_GET","_POST"]},"time_utc":"2026-09-18T05:58:47+00:00","trace_head":"#0 src/XF/Http/Response.php(293): XF\\Http\\Response->sendBody()\n#1 src/XF.php(894): XF\\Http\\Response->send(Object(XF\\Http\\Request))\n#2 index.php(23): XF::runApp('XF\\\\Pub\\\\App')\n#3 {main}"},{"error_id":3,"exception_type":"TypeError","filename_basename":"Response.php","line":490,"message":"strlen(): Argument #1 ($string) must be of type string, XF\\Http\\Response given","request_state":{"bytes":160,"collection_keys":{"_GET":["/support/service-worker"],"_POST":[]},"fields":{"referrer":{"host":"codevipe.ru","path":"/support/staff/ticket"},"url":{"host":null,"path":"/support/service-worker"}},"format":"json","sha256":"bf0540e9fdbe13a7e735692f32f0ebe88e3d872ce50068b9165a7546eef32fdf","top_keys":["url","referrer","_GET","_POST"]},"time_utc":"2026-09-18T05:58:32+00:00","trace_head":"#0 src/XF/Http/Response.php(293): XF\\Http\\Response->sendBody()\n#1 src/XF.php(894): XF\\Http\\Response->send(Object(XF\\Http\\Request))\n#2 index.php(23): XF::runApp('XF\\\\Pub\\\\App')\n#3 {main}"},{"error_id":2,"exception_type":"TypeError","filename_basename":"Response.php","line":490,"message":"strlen(): Argument #1 ($string) must be of type string, XF\\Http\\Response given","request_state":{"bytes":160,"collection_keys":{"_GET":["/support/service-worker"],"_POST":[]},"fields":{"referrer":{"host":"codevipe.ru","path":"/support/staff/ticket"},"url":{"host":null,"path":"/support/service-worker"}},"format":"json","sha256":"bf0540e9fdbe13a7e735692f32f0ebe88e3d872ce50068b9165a7546eef32fdf","top_keys":["url","referrer","_GET","_POST"]},"time_utc":"2026-09-18T05:58:26+00:00","trace_head":"#0 src/XF/Http/Response.php(293): XF\\Http\\Response->sendBody()\n#1 src/XF.php(894): XF\\Http\\Response->send(Object(XF\\Http\\Request))\n#2 index.php(23): XF::runApp('XF\\\\Pub\\\\App')\n#3 {main}"},{"error_id":1,"exception_type":"TypeError","filename_basename":"Response.php","line":490,"message":"strlen(): Argument #1 ($string) must be of type string, XF\\Http\\Response given","request_state":{"bytes":137,"collection_keys":{"_GET":["/support/service-worker"],"_POST":[]},"fields":{"referrer":{"host":"codevipe.ru","path":"/support/staff"},"url":{"host":null,"path":"/support/service-worker"}},"format":"json","sha256":"c809fa5b352e5cabae7067d8626171f788a8dd768fe250455dae052ff2489348","top_keys":["url","referrer","_GET","_POST"]},"time_utc":"2026-09-18T05:54:03+00:00","trace_head":"#0 src/XF/Http/Response.php(293): XF\\Http\\Response->sendBody()\n#1 src/XF.php(894): XF\\Http\\Response->send(Object(XF\\Http\\Request))\n#2 index.php(23): XF::runApp('XF\\\\Pub\\\\App')\n#3 {main}"}]},"source":{"Gram/Support/Pub/Controller/StaffSupport.php":{"basename":"StaffSupport.php","matches":[{"sep":true},{"line":20,"text":""},{"line":21,"text":" if (!$visitor->user_id || !$allowed)"},{"line":22,"text":" {"},{"line":23,"text":" throw $this->exception($this->noPermission());"},{"line":24,"text":" }"},{"line":25,"text":" }"},{"line":26,"text":""},{"line":27,"text":" public function actionIndex()"},{"line":28,"text":" {"},{"line":29,"text":" $this->assertStaff(false);"},{"line":30,"text":""},{"line":31,"text":" $tickets = $this->repository('Gram\\Support:Ticket')"},{"line":32,"text":" ->findStaffQueue()"},{"line":33,"text":" ->fetch();"},{"line":34,"text":""},{"line":35,"text":" return $this->view("},{"line":36,"text":" 'Gram\\Support:StaffQueue',"},{"line":37,"text":" 'gram_support_staff_queue',"},{"line":38,"text":" ['tickets' => $tickets]"},{"line":39,"text":" );"},{"line":40,"text":" }"},{"line":41,"text":""},{"line":42,"text":" public function actionTicket()"},{"line":43,"text":" {"},{"line":44,"text":" $this->assertStaff(false);"},{"line":45,"text":" $ticket = $this->assertTicket();"},{"line":46,"text":""},{"line":47,"text":" $messages = $this->repository('Gram\\Support:Message')"},{"line":48,"text":" ->findAllForTicket((int)$ticket->ticket_id)"},{"line":49,"text":" ->fetch();"},{"line":50,"text":""},{"line":51,"text":" return $this->view("},{"line":52,"text":" 'Gram\\Support:StaffTicket',"},{"line":53,"text":" 'gram_support_staff_ticket',"},{"line":54,"text":" ["},{"line":55,"text":" 'ticket' => $ticket,"},{"line":56,"text":" 'messages' => $messages,"},{"line":57,"text":" 'statusOptions' => StatusPolicy::all()"},{"line":58,"text":" ]"},{"line":59,"text":" );"},{"line":60,"text":" }"},{"line":61,"text":""},{"line":62,"text":" public function actionReply()"},{"line":63,"text":" {"},{"line":64,"text":" $this->assertPostOnly();"},{"line":65,"text":" $this->assertStaff(true);"},{"line":66,"text":""},{"line":67,"text":" $ticket = $this->assertTicket();"},{"line":68,"text":" $isInternal = (bool)$this->filter('is_internal', 'bool');"},{"line":69,"text":""},{"line":70,"text":" if ($isInternal"},{"line":71,"text":" && !\\XF::visitor()->hasPermission('gramSupport', 'internalNotes'))"},{"line":72,"text":" {"},{"line":73,"text":" return $this->noPermission();"},{"line":74,"text":" }"},{"line":75,"text":""},{"line":76,"text":" /** @var Reply $reply */"},{"line":77,"text":" $reply = $this->service(Reply::class);"},{"line":78,"text":" $reply->add("},{"line":79,"text":" $ticket,"},{"line":80,"text":" $this->filter('message', 'str'),"},{"line":81,"text":" true,"},{"line":82,"text":" $isInternal"},{"line":83,"text":" );"},{"line":84,"text":""},{"line":85,"text":" return $this->redirect("},{"line":86,"text":" $this->buildLink('support/staff/ticket', null, ['ref' => $ticket->public_ref])"},{"line":87,"text":" );"},{"line":88,"text":" }"},{"line":89,"text":""},{"line":90,"text":" public function actionUpdate()"},{"line":91,"text":" {"},{"line":92,"text":" $this->assertPostOnly();"},{"line":93,"text":" $this->assertStaff(true);"},{"line":94,"text":""},{"line":95,"text":" $ticket = $this->assertTicket();"},{"line":96,"text":" $newStatus = trim($this->filter('status', 'str'));"},{"line":97,"text":" $assignedUserId = (int)$this->filter('assigned_user_id', 'uint');"},{"sep":true},{"line":100,"text":" $staffUpdate = $this->service(StaffUpdate::class);"},{"line":101,"text":" $staffUpdate->validateTransition((string)$ticket->status, $newStatus);"},{"line":102,"text":""},{"line":103,"text":" if ($assignedUserId > 0)"},{"line":104,"text":" {"},{"line":105,"text":" if (!\\XF::visitor()->hasPermission('gramSupport', 'assign'))"},{"line":106,"text":" {"},{"line":107,"text":" return $this->noPermission();"},{"line":108,"text":" }"},{"line":109,"text":""},{"line":110,"text":" $assigned = \\XF::em()->find('XF:User', $assignedUserId);"},{"line":111,"text":" if (!$assigned"},{"line":112,"text":" || (!$assigned->hasPermission('gramSupport', 'viewAll')"},{"line":113,"text":" && !$assigned->hasPermission('gramSupport', 'manage')))"},{"line":114,"text":" {"},{"line":115,"text":" return $this->error(\\XF::phrase('gram_support_assignee_invalid'));"},{"line":116,"text":" }"},{"line":117,"text":" }"},{"line":118,"text":""},{"line":119,"text":" $oldStatus = (string)$ticket->status;"},{"line":120,"text":" $oldAssigned = (int)$ticket->assigned_user_id;"},{"line":121,"text":""},{"line":122,"text":" $db = \\XF::db();"},{"sep":true},{"line":154,"text":" {"},{"line":155,"text":" $db->rollback();"},{"line":156,"text":" throw $e;"},{"line":157,"text":" }"},{"line":158,"text":""},{"line":159,"text":" (new EventDispatcher())->dispatchSafely($event, $ticket);"},{"line":160,"text":""},{"line":161,"text":" return $this->redirect("},{"line":162,"text":" $this->buildLink('support/staff/ticket', null, ['ref' => $ticket->public_ref])"},{"line":163,"text":" );"},{"line":164,"text":" }"},{"line":165,"text":""},{"line":166,"text":" private function assertTicket()"},{"line":167,"text":" {"},{"line":168,"text":" $ticket = $this->repository('Gram\\Support:Ticket')"},{"line":169,"text":" ->findByPublicRef($this->filter('ref', 'str'));"},{"line":170,"text":""},{"line":171,"text":" if (!$ticket)"},{"line":172,"text":" {"},{"line":173,"text":" throw $this->exception($this->notFound());"},{"line":174,"text":" }"},{"line":175,"text":""},{"line":176,"text":" return $ticket;"},{"line":177,"text":" }"},{"line":178,"text":"}"}],"present":true},"Gram/Support/Pub/Controller/Support.php":{"basename":"Support.php","matches":[{"sep":true},{"line":10,"text":"use Gram\\Support\\Service\\Ticket\\Creator;"},{"line":11,"text":"use Gram\\Support\\Service\\Ticket\\Reply;"},{"line":12,"text":"use Gram\\Support\\Util\\SiteConfig;"},{"line":13,"text":"use XF\\Mvc\\ParameterBag;"},{"line":14,"text":""},{"line":15,"text":"final class Support extends \\XF\\Pub\\Controller\\AbstractController"},{"line":16,"text":"{"},{"line":17,"text":" public function actionIndex()"},{"line":18,"text":" {"},{"line":19,"text":" if (\\XF::visitor()->user_id)"},{"line":20,"text":" {"},{"line":21,"text":" return $this->redirect($this->buildLink('account/support'));"},{"line":22,"text":" }"},{"line":23,"text":""},{"line":24,"text":" return $this->redirect($this->buildLink('support/create'));"},{"line":25,"text":" }"},{"line":26,"text":""},{"line":27,"text":" public function actionCreate()"},{"line":28,"text":" {"},{"line":29,"text":" $visitor = \\XF::visitor();"},{"line":30,"text":""},{"line":31,"text":" if ($visitor->user_id && !$visitor->hasPermission('gramSupport', 'create'))"},{"line":32,"text":" {"},{"line":33,"text":" return $this->noPermission();"},{"line":34,"text":" }"},{"line":35,"text":""},{"line":36,"text":" if ($this->isPost())"},{"line":37,"text":" {"},{"line":38,"text":" $this->assertPostOnly();"},{"line":39,"text":""},{"line":40,"text":" $email = $this->filter('email', 'str');"},{"sep":true},{"line":42,"text":" $subject = $this->filter('subject', 'str');"},{"line":43,"text":" $message = $this->filter('message', 'str');"},{"line":44,"text":""},{"line":45,"text":" if (!$visitor->user_id)"},{"line":46,"text":" {"},{"line":47,"text":" if (!$this->captchaIsValid(true))"},{"line":48,"text":" {"},{"line":49,"text":" return $this->error("},{"line":50,"text":" \\XF::phrase('did_not_complete_the_captcha_verification_properly')"},{"line":51,"text":" );"},{"line":52,"text":" }"},{"line":53,"text":""},{"line":54,"text":" /** @var RateLimiter $rateLimiter */"},{"line":55,"text":" $rateLimiter = $this->service(RateLimiter::class);"},{"line":56,"text":" $allowed = $rateLimiter->consumeGuest("},{"sep":true},{"line":58,"text":" $email,"},{"line":59,"text":" SiteConfig::guestRateLimitCount(),"},{"line":60,"text":" SiteConfig::guestRateLimitWindowSeconds()"},{"line":61,"text":" );"},{"line":62,"text":""},{"line":63,"text":" if (!$allowed)"},{"line":64,"text":" {"},{"line":65,"text":" return $this->error(\\XF::phrase('gram_support_rate_limited'));"},{"line":66,"text":" }"},{"line":67,"text":" }"},{"line":68,"text":""},{"line":69,"text":" $upload = $this->request->getFile('screenshot', false, false);"},{"line":70,"text":" $tempHash = bin2hex(random_bytes(16));"},{"line":71,"text":" $attachmentFlow = new GuestTicketCreateAttachmentFlow();"},{"line":72,"text":""},{"sep":true},{"line":106,"text":" }"},{"line":107,"text":" }"},{"line":108,"text":""},{"line":109,"text":" if ($created['guest_secret'])"},{"line":110,"text":" {"},{"line":111,"text":" $secret = (string)$created['guest_secret'];"},{"line":112,"text":""},{"line":113,"text":" return $this->view("},{"line":114,"text":" 'Gram\\Support:CreatedGuest',"},{"line":115,"text":" 'gram_support_created_guest',"},{"line":116,"text":" ["},{"line":117,"text":" 'ticket' => $ticket,"},{"line":118,"text":" 'accessCode' => $secret,"},{"line":119,"text":" 'magicLink' => $this->buildLink('canonical:support/access') . '#token=' . rawurlencode($secret)"},{"line":120,"text":" ]"},{"line":121,"text":" );"},{"line":122,"text":" }"},{"line":123,"text":""},{"line":124,"text":" return $this->redirect("},{"line":125,"text":" $this->buildLink('support/ticket', null, ['ref' => $ticket->public_ref])"},{"line":126,"text":" );"},{"line":127,"text":" }"},{"line":128,"text":""},{"line":129,"text":" return $this->view("},{"line":130,"text":" 'Gram\\Support:Create',"},{"line":131,"text":" 'gram_support_create',"},{"line":132,"text":" ['forceCaptcha' => !$visitor->user_id]"},{"line":133,"text":" );"},{"line":134,"text":" }"},{"line":135,"text":""},{"line":136,"text":" public function actionAccess()"},{"line":137,"text":" {"},{"line":138,"text":" if ($this->isPost())"},{"line":139,"text":" {"},{"line":140,"text":" $this->assertPostOnly();"},{"line":141,"text":""},{"line":142,"text":" $secret = trim($this->filter('access_code', 'str'));"},{"line":143,"text":" if ($secret === '')"},{"line":144,"text":" {"},{"line":145,"text":" return $this->error(\\XF::phrase('gram_support_access_code_required'));"},{"line":146,"text":" }"},{"line":147,"text":""},{"line":148,"text":" $ticket = $this->repository('Gram\\Support:Ticket')"},{"line":149,"text":" ->findGuestAccessibleBySecret($secret, \\XF::$time);"},{"line":150,"text":""},{"line":151,"text":" if (!$ticket)"},{"line":152,"text":" {"},{"line":153,"text":" return $this->error(\\XF::phrase('gram_support_access_invalid'));"},{"line":154,"text":" }"},{"line":155,"text":""},{"line":156,"text":" GuestTicketSession::grant($ticket);"},{"line":157,"text":""},{"line":158,"text":" return $this->redirect("},{"line":159,"text":" $this->buildLink('support/ticket', null, ['ref' => $ticket->public_ref])"},{"line":160,"text":" );"},{"line":161,"text":" }"},{"line":162,"text":""},{"line":163,"text":" return $this->view("},{"line":164,"text":" 'Gram\\Support:Access',"},{"line":165,"text":" 'gram_support_access',"},{"line":166,"text":" []"},{"line":167,"text":" );"},{"line":168,"text":" }"},{"line":169,"text":""},{"line":170,"text":" public function actionTicket()"},{"line":171,"text":" {"},{"line":172,"text":" $ticket = $this->assertViewableTicketByRef($this->filter('ref', 'str'));"},{"line":173,"text":""},{"line":174,"text":" $messages = $this->repository('Gram\\Support:Message')"},{"line":175,"text":" ->findPublicForTicket((int)$ticket->ticket_id)"},{"line":176,"text":" ->fetch();"},{"line":177,"text":""},{"line":178,"text":" return $this->view("},{"line":179,"text":" 'Gram\\Support:Ticket',"},{"line":180,"text":" 'gram_support_ticket',"},{"line":181,"text":" ["},{"line":182,"text":" 'ticket' => $ticket,"},{"line":183,"text":" 'messages' => $messages"},{"line":184,"text":" ]"},{"line":185,"text":" );"},{"line":186,"text":" }"},{"line":187,"text":""},{"line":188,"text":" public function actionReply()"},{"line":189,"text":" {"},{"line":190,"text":" $this->assertPostOnly();"},{"line":191,"text":""},{"line":192,"text":" $ticket = $this->assertViewableTicketByRef($this->filter('ref', 'str'));"},{"line":193,"text":" $visitor = \\XF::visitor();"},{"line":194,"text":""},{"line":195,"text":" if ($visitor->user_id)"},{"line":196,"text":" {"},{"line":197,"text":" if ((int)$ticket->user_id !== (int)$visitor->user_id"},{"line":198,"text":" || !$visitor->hasPermission('gramSupport', 'replyOwn'))"},{"line":199,"text":" {"},{"line":200,"text":" return $this->noPermission();"},{"line":201,"text":" }"},{"line":202,"text":" }"},{"line":203,"text":" elseif (!GuestTicketSession::hasGrant($ticket))"},{"line":204,"text":" {"},{"line":205,"text":" return $this->noPermission();"},{"line":206,"text":" }"},{"line":207,"text":""},{"line":208,"text":" $message = $this->filter('message', 'str');"},{"line":209,"text":""},{"line":210,"text":" /** @var Reply $reply */"},{"line":211,"text":" $reply = $this->service(Reply::class);"},{"line":212,"text":" $reply->add($ticket, $message, false, false);"},{"line":213,"text":""},{"line":214,"text":" return $this->redirect("},{"line":215,"text":" $this->buildLink('support/ticket', null, ['ref' => $ticket->public_ref])"},{"line":216,"text":" );"},{"line":217,"text":" }"},{"line":218,"text":""},{"line":219,"text":" private function assertViewableTicketByRef(string $publicRef)"},{"line":220,"text":" {"}],"present":true},"XF/Http/Response.php":{"basename":"Response.php","matches":[{"sep":true},{"line":240,"text":"\t\treturn $name;"},{"line":241,"text":"\t}"},{"line":242,"text":""},{"line":243,"text":"\tpublic function body($body = null)"},{"line":244,"text":"\t{"},{"line":245,"text":"\t\tif ($body === null)"},{"line":246,"text":"\t\t{"},{"line":247,"text":"\t\t\treturn $this->body;"},{"line":248,"text":"\t\t}"},{"line":249,"text":""},{"line":250,"text":"\t\t$this->body = $body;"},{"line":251,"text":""},{"line":252,"text":"\t\treturn $this;"},{"line":253,"text":"\t}"},{"line":254,"text":""},{"line":255,"text":"\tpublic function responseFile($fileName)"},{"line":256,"text":"\t{"},{"line":257,"text":"\t\treturn new ResponseFile($fileName);"},{"sep":true},{"line":282,"text":"\t\t}"},{"line":283,"text":""},{"line":284,"text":"\t\t$this->includeContentLength = (bool) $use;"},{"line":285,"text":""},{"line":286,"text":"\t\treturn $this;"},{"line":287,"text":"\t}"},{"line":288,"text":""},{"line":289,"text":"\tpublic function send(?Request $request = null)"},{"line":290,"text":"\t{"},{"line":291,"text":"\t\t$this->prepareForOutput($request);"},{"line":292,"text":"\t\t$this->sendHeaders();"},{"line":293,"text":"\t\t$this->sendBody();"},{"line":294,"text":"\t}"},{"line":295,"text":""},{"line":296,"text":"\tpublic function prepareForOutput(?Request $request = null)"},{"sep":true},{"line":381,"text":"\tpublic function removeCookie($name)"},{"line":382,"text":"\t{"},{"line":383,"text":"\t\tunset($this->cookies[$name]);"},{"line":384,"text":""},{"line":385,"text":"\t\treturn $this;"},{"line":386,"text":"\t}"},{"line":387,"text":""},{"line":388,"text":"\tpublic function sendHeaders()"},{"line":389,"text":"\t{"},{"line":390,"text":"\t\tforeach ($this->headers AS $key => $value)"},{"line":391,"text":"\t\t{"},{"line":392,"text":"\t\t\tif (is_array($value))"},{"line":393,"text":"\t\t\t{"},{"line":394,"text":"\t\t\t\tforeach ($value AS $innerValue)"},{"line":395,"text":"\t\t\t\t{"},{"sep":true},{"line":446,"text":"\t\t\t\t}"},{"line":447,"text":""},{"line":448,"text":"\t\t\t\tcall_user_func('setcookie', $name, $value, $options);"},{"line":449,"text":"\t\t\t}"},{"line":450,"text":"\t\t}"},{"line":451,"text":"\t}"},{"line":452,"text":""},{"line":453,"text":"\tpublic function sendBody()"},{"line":454,"text":"\t{"},{"line":455,"text":"\t\tif ($this->body instanceof ResponseFile)"},{"line":456,"text":"\t\t{"},{"line":457,"text":"\t\t\tif ($this->includeContentLength)"},{"line":458,"text":"\t\t\t{"},{"line":459,"text":"\t\t\t\theader('Content-Length: ' . $this->body->getLength());"},{"line":460,"text":"\t\t\t}"},{"line":461,"text":""},{"line":462,"text":"\t\t\t$this->body->output();"},{"line":463,"text":"\t\t}"},{"line":464,"text":"\t\telse if ($this->body instanceof ResponseStream)"},{"line":465,"text":"\t\t{"},{"line":466,"text":"\t\t\tif ($this->includeContentLength)"},{"line":467,"text":"\t\t\t{"},{"line":468,"text":"\t\t\t\t$length = $this->body->getLength();"},{"line":469,"text":"\t\t\t\tif ($length !== null)"},{"line":470,"text":"\t\t\t\t{"},{"line":471,"text":"\t\t\t\t\theader('Content-Length: ' . $length);"},{"line":472,"text":"\t\t\t\t}"},{"line":473,"text":"\t\t\t}"},{"line":474,"text":""},{"line":475,"text":"\t\t\t$this->body->output();"},{"line":476,"text":"\t\t}"},{"line":477,"text":"\t\telse"},{"line":478,"text":"\t\t{"},{"line":479,"text":"\t\t\tif ($this->compress)"},{"line":480,"text":"\t\t\t{"},{"line":481,"text":"\t\t\t\t$toPrint = gzencode($this->body, 9);"},{"line":482,"text":"\t\t\t}"},{"line":483,"text":"\t\t\telse"},{"line":484,"text":"\t\t\t{"},{"line":485,"text":"\t\t\t\t$toPrint = $this->body;"},{"line":486,"text":"\t\t\t}"},{"line":487,"text":""},{"line":488,"text":"\t\t\tif ($this->includeContentLength)"},{"line":489,"text":"\t\t\t{"},{"line":490,"text":"\t\t\t\theader('Content-Length: ' . strlen($toPrint));"},{"line":491,"text":"\t\t\t}"},{"line":492,"text":""},{"line":493,"text":"\t\t\techo $toPrint;"},{"line":494,"text":"\t\t}"},{"line":495,"text":"\t}"},{"line":496,"text":""},{"line":497,"text":"\tpublic function contentIsCompressible(Request $request)"},{"line":498,"text":"\t{"},{"line":499,"text":"\t\tif ("},{"line":500,"text":"\t\t\t!is_string($this->body)"},{"line":501,"text":"\t\t\t|| !preg_match('#^(?:text/|application/(?:json|xml|rss\\+xml)$)#i', $this->contentType)"},{"line":502,"text":"\t\t\t|| strpos($request->getServer('HTTP_ACCEPT_ENCODING', ''), 'gzip') === false"},{"line":503,"text":"\t\t)"},{"line":504,"text":"\t\t{"},{"line":505,"text":"\t\t\treturn false;"},{"line":506,"text":"\t\t}"},{"line":507,"text":""},{"line":508,"text":"\t\tif (!function_exists('gzencode'))"},{"line":509,"text":"\t\t{"},{"line":510,"text":"\t\t\treturn false;"},{"line":511,"text":"\t\t}"},{"line":512,"text":""},{"line":513,"text":"\t\treturn (strlen($this->body) >= 20);"},{"line":514,"text":"\t}"},{"line":515,"text":"}"}],"present":true}}},"guest_stderr_present":false,"inner_rc":0,"ok":true,"out_truncated":false,"transport_rc":0,"transport_stderr_bytes":0,"transport_stderr_sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}
-GRAM516R5RCA3_DECISION=PASS_ERROR_REQUESTSTATE_AND_SOURCE_CAPTURED
-GRAM516R5RCA3_NEXT_GATE=CLASSIFY_CURRENT_RUNTIME_DEFECT
-HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260918-GRAM-SUPPORT-CODEVIPE-ERROR-REQUESTSTATE-RCA-READONLY-516R5RCA3","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null}
+GRAM516R5RCA4_SAFE_REPORT={"err_truncated":false,"guest":{"core":[{"matches":[{"sep":true},{"line":125,"text":"\t\tswitch (get_class($reply))"},{"line":126,"text":"\t\t{"},{"line":127,"text":"\t\t\tcase Redirect::class:"},{"line":128,"text":"\t\t\tcase Reroute::class:"},{"line":129,"text":"\t\t\t\treturn false; // don't update anything, assume the next page will do it"},{"line":130,"text":""},{"line":131,"text":"\t\t\tcase Message::class:"},{"line":132,"text":"\t\t\tcase View::class:"},{"line":133,"text":"\t\t\t\t$viewState = 'valid';"},{"line":134,"text":"\t\t\t\tbreak;"},{"line":135,"text":"\t\t}"},{"line":136,"text":""},{"line":137,"text":"\t\tif ($reply->getResponseCode() >= 400)"},{"line":138,"text":"\t\t{"},{"line":139,"text":"\t\t\t$viewState = 'error';"},{"line":140,"text":"\t\t}"},{"line":141,"text":""},{"line":142,"text":"\t\treturn true;"},{"line":143,"text":"\t}"},{"line":144,"text":""},{"line":145,"text":"\tpublic function checkTfaRedirect()"},{"line":146,"text":"\t{"},{"line":147,"text":"\t\t$session = $this->session();"},{"line":148,"text":"\t\tif ($session->tfaLoginRedirect)"},{"line":149,"text":"\t\t{"},{"sep":true},{"line":219,"text":"\tpublic function assertNotDisabled($action)"},{"line":220,"text":"\t{"},{"line":221,"text":"\t\tif (\\XF::visitor()->user_state == 'disabled')"},{"line":222,"text":"\t\t{"},{"line":223,"text":"\t\t\tthrow $this->exception("},{"line":224,"text":"\t\t\t\t$this->plugin(ErrorPlugin::class)->actionDisabled()"},{"line":225,"text":"\t\t\t);"},{"line":226,"text":"\t\t}"},{"line":227,"text":"\t}"},{"line":228,"text":""},{"line":229,"text":"\tpublic function assertCanonicalBaseUrl($action)"},{"line":230,"text":"\t{"},{"line":231,"text":"\t\tif ($this->responseType != 'html')"},{"line":232,"text":"\t\t{"},{"line":233,"text":"\t\t\treturn;"},{"line":234,"text":"\t\t}"},{"line":235,"text":""},{"line":236,"text":"\t\tif (!$this->request->isGet() && !$this->request->isHead())"},{"line":237,"text":"\t\t{"},{"line":238,"text":"\t\t\treturn;"},{"line":239,"text":"\t\t}"},{"line":240,"text":""},{"line":241,"text":"\t\t$options = $this->options();"},{"line":242,"text":"\t\tif (!$options->boardUrlCanonical)"},{"line":243,"text":"\t\t{"},{"sep":true},{"line":273,"text":""},{"line":274,"text":"\t\t\tthrow $this->exception($reply);"},{"line":275,"text":"\t\t}"},{"line":276,"text":"\t}"},{"line":277,"text":""},{"line":278,"text":"\tpublic function assertBoardActive($action)"},{"line":279,"text":"\t{"},{"line":280,"text":"\t\t$options = $this->options();"},{"line":281,"text":"\t\tif (!$options->boardActive && !\\XF::visitor()->is_admin)"},{"line":282,"text":"\t\t{"},{"line":283,"text":"\t\t\t$reply = $this->message(new PreEscaped($options->boardInactiveMessage), $this->app->config('serviceUnavailableCode'));"},{"line":284,"text":"\t\t\t$reply->setPageParam('skipSidebarWidgets', true);"},{"line":285,"text":"\t\t\t$reply->setResponseHeader('Retry-After', 60);"},{"line":286,"text":"\t\t\t$reply->setResponseHeader('Refresh', 60);"},{"line":287,"text":""},{"line":288,"text":"\t\t\tthrow $this->exception($reply);"},{"line":289,"text":"\t\t}"},{"line":290,"text":"\t}"},{"line":291,"text":""},{"line":292,"text":"\tpublic function assertTfaRequirement($action)"},{"line":293,"text":"\t{"},{"line":294,"text":"\t\t$visitor = \\XF::visitor();"},{"line":295,"text":"\t\tif ($visitor->user_id"},{"line":296,"text":"\t\t\t&& empty($visitor->Option->use_tfa)"},{"line":297,"text":"\t\t\t&& \\XF::config('enableTfa')"},{"line":298,"text":"\t\t\t&& $visitor->hasPermission('general', 'requireTfa')"},{"sep":true},{"line":459,"text":"\t\treturn in_array($requestRoutePath, $whitelistRoutePaths, true);"},{"line":460,"text":"\t}"},{"line":461,"text":""},{"line":462,"text":"\tpublic function isEmbeddedImageRequest(): bool"},{"line":463,"text":"\t{"},{"line":464,"text":"\t\treturn $this->request->isEmbeddedImageRequest();"},{"line":465,"text":"\t}"},{"line":466,"text":""},{"line":467,"text":"\tpublic function assertNotEmbeddedImageRequest()"},{"line":468,"text":"\t{"},{"line":469,"text":"\t\tif ($this->isEmbeddedImageRequest())"},{"line":470,"text":"\t\t{"},{"line":471,"text":"\t\t\t$this->setResponseType('raw');"},{"line":472,"text":""},{"line":473,"text":"\t\t\t$view = $this->view('XF:Error\\EmbeddedImageRequest');"},{"line":474,"text":"\t\t\t$view->setResponseCode(406);"},{"line":475,"text":""},{"line":476,"text":"\t\t\tthrow $this->exception($view);"},{"line":477,"text":"\t\t}"},{"line":478,"text":"\t}"},{"line":479,"text":""},{"line":480,"text":"\tpublic function hasContentPendingApproval()"},{"line":481,"text":"\t{"},{"line":482,"text":"\t\t$pendingUntil = $this->session()->hasContentPendingUntil;"},{"line":483,"text":"\t\treturn ($pendingUntil && $pendingUntil >= \\XF::$time);"},{"line":484,"text":"\t}"},{"line":485,"text":""},{"line":486,"text":"\tprotected function isDiscouraged()"},{"sep":true},{"line":565,"text":"\tpublic function assertNotFlooding($action, $floodingLimit = null)"},{"line":566,"text":"\t{"},{"line":567,"text":"\t\t$visitor = \\XF::visitor();"},{"line":568,"text":"\t\tif ($visitor->hasPermission('general', 'bypassFloodCheck'))"},{"line":569,"text":"\t\t{"},{"line":570,"text":"\t\t\treturn;"},{"line":571,"text":"\t\t}"},{"line":572,"text":""},{"line":573,"text":"\t\t$floodChecker = $this->service(FloodCheckService::class);"},{"line":574,"text":"\t\t$timeRemaining = $floodChecker->checkFlooding($action, $visitor->user_id, $floodingLimit);"},{"line":575,"text":"\t\tif ($timeRemaining)"},{"line":576,"text":"\t\t{"},{"line":577,"text":"\t\t\tthrow $this->exception($this->responseFlooding($timeRemaining));"},{"line":578,"text":"\t\t}"},{"line":579,"text":"\t}"},{"line":580,"text":""},{"line":581,"text":"\tpublic function responseFlooding($floodSeconds)"},{"line":582,"text":"\t{"},{"line":583,"text":"\t\treturn $this->error(\\XF::phrase('must_wait_x_seconds_before_performing_this_action', ['count' => $floodSeconds]));"},{"line":584,"text":"\t}"},{"line":585,"text":""},{"line":586,"text":"\tpublic function isRobot()"},{"line":587,"text":"\t{"},{"line":588,"text":"\t\treturn boolval($this->request->getRobotName());"},{"line":589,"text":"\t}"},{"line":590,"text":""},{"line":591,"text":"\t/**"},{"line":592,"text":"\t * @return IpRepository"},{"line":593,"text":"\t */"}],"path":"src/XF/Pub/Controller/AbstractController.php","present":true,"sha256":"023efffff88cd1675173f30a8104d25fb220a5d8dc989d89c33d3ba09b0c0169"}],"error":null,"files":[{"matches":[],"path":"Pub/Controller/Support.php","present":true,"sha256":"6cb34b1d27e9f0132263637cefa62fe0e998a9a86620b7ac33199f41ee86f9d4"},{"matches":[],"path":"Pub/Controller/StaffSupport.php","present":true,"sha256":"6852bd0061d6e118851673bfd4099e2b22e6291bf09f429820740844996f93f9"},{"matches":[{"sep":true},{"line":1,"text":""},{"line":2,"text":""},{"line":3,"text":" "},{"line":4,"text":" "},{"line":5,"text":" "},{"line":6,"text":" "},{"line":7,"text":""}],"path":"_data/routes.xml","present":true,"sha256":"c80e6b0f7153993915d8bbc8ee6b36e6386b00bb1865d6aff050f9c1fd1f0302"},{"matches":[{"sep":true},{"line":553,"text":"<xf:if is=\"$xf.options.gramSupportSiteId\">"},{"line":554,"text":"\t<a class=\"gramSupport-launcher button button--primary\""},{"line":555,"text":"\t\thref=\"{{ link('support/create') }}\""},{"line":556,"text":"\t\taria-label=\"{{ phrase('gram_support_open_support') }}\">"},{"line":557,"text":"\t\t{{ phrase('gram_support_open_support') }}"},{"line":558,"text":"\t</a>"},{"line":559,"text":"</xf:if>"},{"line":560,"text":""},{"line":561,"text":" <xf:title>{{ phrase('gram_support_staff_queue') }}</xf:title>"},{"line":562,"text":"<xf:css src=\"gram_support.less\" />"},{"line":563,"text":"<span class=\"js-gramSupportPwaConfig\" hidden"},{"line":564,"text":"\tdata-manifest-url=\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\""},{"line":565,"text":"\tdata-sw-url=\"{{ link('support/service-worker') }}\"></span>"},{"line":566,"text":"<xf:js addon=\"Gram/Support\" src=\"gram/support/staff-pwa.js\" min=\"1\" />"},{"line":567,"text":""},{"line":568,"text":"<div class=\"block\">"},{"line":569,"text":"\t<div class=\"block-container\">"},{"line":570,"text":"\t\t<div class=\"block-body\">"},{"line":571,"text":"\t\t\t<xf:foreach loop=\"$tickets\" value=\"$ticket\">"},{"line":572,"text":"\t\t\t\t<div class=\"block-row\">"},{"line":573,"text":"\t\t\t\t\t<a href=\"{{ link('support/staff/ticket', null, {'ref': $ticket.public_ref}) }}\">"},{"line":574,"text":"\t\t\t\t\t\t{{ $ticket.public_ref }} \u2014 {{ $ticket.subject }}"},{"line":575,"text":"\t\t\t\t\t</a>"},{"line":576,"text":"\t\t\t\t\t<span class=\"u-muted\">"},{"line":577,"text":"<xf:if is=\"$ticket.status == 'NEW'\">\u041d\u043e\u0432\u044b\u0439"},{"sep":true},{"line":579,"text":"<xf:elseif is=\"$ticket.status == 'WAITING_USER'\" />\u041e\u0436\u0438\u0434\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f"},{"line":580,"text":"<xf:elseif is=\"$ticket.status == 'RESOLVED'\" />\u0420\u0435\u0448\u0451\u043d"},{"line":581,"text":"<xf:elseif is=\"$ticket.status == 'CLOSED'\" />\u0417\u0430\u043a\u0440\u044b\u0442"},{"line":582,"text":"<xf:else />{{ $ticket.status }}"},{"line":583,"text":"</xf:if>"},{"line":584,"text":"</span>"},{"line":585,"text":"\t\t\t\t</div>"},{"line":586,"text":"\t\t\t</xf:foreach>"},{"line":587,"text":"\t\t</div>"},{"line":588,"text":"\t</div>"},{"line":589,"text":"</div>"},{"line":590,"text":""},{"line":591,"text":" 'use strict';"},{"line":592,"text":""},{"line":593,"text":"const OFFLINE_URL = '{{ base_url('js/gram/support/pwa/offline.html')|escape('js') }}';"},{"line":594,"text":"const STATIC_CACHE = 'gram-support-staff-static-v1';"},{"line":595,"text":""},{"line":596,"text":"self.addEventListener('install', event => {"},{"line":597,"text":"\tevent.waitUntil("},{"line":598,"text":"\t\tcaches.open(STATIC_CACHE)"},{"line":599,"text":"\t\t\t.then(cache => cache.addAll([OFFLINE_URL]))"},{"line":600,"text":"\t\t\t.then(() => self.skipWaiting())"},{"line":601,"text":"\t);"},{"line":602,"text":"});"},{"line":603,"text":""},{"sep":true},{"line":655,"text":"\t\t\t\t\treturn response;"},{"line":656,"text":"\t\t\t\t});"},{"line":657,"text":"\t\t\t\treturn cached || network;"},{"line":658,"text":"\t\t\t})"},{"line":659,"text":"\t\t)"},{"line":660,"text":"\t);"},{"line":661,"text":"});"},{"line":662,"text":""},{"line":663,"text":" <xf:title>{{ phrase('gram_support_staff_ticket') }} {{ $ticket.public_ref }}</xf:title>"},{"line":664,"text":"<xf:css src=\"gram_support.less\" />"},{"line":665,"text":"<span class=\"js-gramSupportPwaConfig\" hidden"},{"line":666,"text":"\tdata-manifest-url=\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\""},{"line":667,"text":"\tdata-sw-url=\"{{ link('support/service-worker') }}\"></span>"},{"line":668,"text":"<xf:js addon=\"Gram/Support\" src=\"gram/support/staff-pwa.js\" min=\"1\" />"},{"line":669,"text":""},{"line":670,"text":"<div class=\"block\">"},{"line":671,"text":"\t<div class=\"block-container\">"},{"line":672,"text":"\t\t<h2 class=\"block-header\">{{ $ticket.public_ref }} \u2014 {{ $ticket.subject }}</h2>"},{"line":673,"text":"\t\t<div class=\"block-body\">"},{"line":674,"text":"\t\t\t<xf:foreach loop=\"$messages\" value=\"$message\">"},{"line":675,"text":"\t\t\t\t<div class=\"block-row {{ $message.is_internal ? 'gramSupport-message--internal' : '' }}\">"},{"line":676,"text":"\t\t\t\t\t<div class=\"gramSupport-messageMeta\">"},{"line":677,"text":"\t\t\t\t\t\t{{ date_time($message.message_date) }}"},{"line":678,"text":"\t\t\t\t\t\t<xf:if is=\"$message.is_internal\"> \u00b7 {{ phrase('gram_support_internal_note') }}</xf:if>"},{"line":679,"text":"\t\t\t\t\t</div>"}],"path":"_data/templates.xml","present":true,"sha256":"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239"},{"matches":[],"path":"addon.json","present":true,"sha256":"566f1739937088517f5ef0dd2d20bc92460084028180c16502931fa86057aea5"}],"occurrences":[{"hit_count":2,"hits":[{"line":25,"text":" 'Gram\\Support:PwaServiceWorker',"},{"line":26,"text":" 'gram_support_staff_service_worker',"}],"path":"Pub/Controller/Pwa.php","sha256":"9e3217d9524349a8137b89d418e4693ca17f8e5f61ba5b563fff747d1014efb3"},{"hit_count":2,"hits":[{"line":5,"text":"class PwaServiceWorker extends \\XF\\Mvc\\View"},{"line":12,"text":" 'public:gram_support_staff_service_worker',"}],"path":"Pub/View/PwaServiceWorker.php","sha256":"700f01f005b818d63267e70dac7669a606c78fabbef5d3e01731c49db3d0be04"},{"hit_count":1,"hits":[{"line":6,"text":" "}],"path":"_data/routes.xml","sha256":"c80e6b0f7153993915d8bbc8ee6b36e6386b00bb1865d6aff050f9c1fd1f0302"},{"hit_count":3,"hits":[{"line":565,"text":"\tdata-sw-url=\"{{ link('support/service-worker') }}\"></span>"},{"line":591,"text":" 'use strict';"},{"line":667,"text":"\tdata-sw-url=\"{{ link('support/service-worker') }}\"></span>"}],"path":"_data/templates.xml","sha256":"04ed000e02dd040f0587cf276f8c2ad332b568c951b58bd5767df78406e10239"},{"hit_count":1,"hits":[{"line":30,"text":" \"src/addons/Gram/Support/Pub/View/PwaServiceWorker.php\": \"700f01f005b818d63267e70dac7669a606c78fabbef5d3e01731c49db3d0be04\","}],"path":"hashes.json","sha256":"1f947a585ee5d5936c6d1c73a7d4602c0f77ceafd98936df74b89a6a4538921f"}],"ok":true},"guest_stderr_present":false,"inner_rc":0,"ok":true,"out_truncated":false,"transport_rc":0,"transport_stderr_bytes":0,"transport_stderr_sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}
+GRAM516R5RCA4_DECISION=PASS_SERVICE_WORKER_SOURCE_EVIDENCE_CAPTURED
+GRAM516R5RCA4_NEXT_GATE=BUILD_EXACT_SERVICE_WORKER_FIX
+HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260918-GRAM-SUPPORT-SERVICE-WORKER-SOURCE-RCA-READONLY-516R5RCA4","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null}
OUTPUT_END
CHAT_OUTPUT_END