1
0
Files
homelab-public-context/runtime/latest.json
T

39 lines
41 KiB
JSON

{
"schema_version": 1,
"channel": "homelab-runtime",
"command_id": "SUPPORT-260918-GRAM-SUPPORT-NOTIFY-CAPTCHA-SOURCE-READONLY-516R1R3",
"status": "OK",
"rc": 0,
"host": "pve01",
"mode": "read-only",
"component": "gram-support-notify-captcha-source-readonly",
"started_at_utc": "2026-09-18T05:06:58Z",
"finished_at_utc": "2026-09-18T05:07:00Z",
"reference_register_checked": true,
"reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66",
"error_register_checked": true,
"error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0",
"command_sha256": "0f7a476d59191ec993679cb3fe3a569eb7e5b72805ab8c6e63c390f6a14915fc",
"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": "6eb6b9ac7ab7b4c61eb06b40dd1f2390fcac654e496097728a954feacd2b3c9c",
"sanitized_output_sha256": "6eb6b9ac7ab7b4c61eb06b40dd1f2390fcac654e496097728a954feacd2b3c9c",
"output_truncated_in_json": false,
"full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
"output": "GRAM516R1R3_SAFE_REPORT={\"err_truncated\":false,\"guest_stderr_present\":false,\"inner_rc\":0,\"ok\":true,\"out_truncated\":false,\"source\":{\"notification_files\":[\"Notification/AlertConsumer.php\",\"Notification/DeliveryGate.php\",\"Notification/Dispatcher.php\",\"Notification/EmailConsumer.php\",\"Notification/EntityDeliveryGate.php\",\"Notification/EventDispatcher.php\",\"Notification/Policy.php\",\"Notification/RecipientKey.php\"],\"ok\":true,\"root_tree_files\":[\"Attachment/TicketHandler.php\",\"Entity/AttachmentMeta.php\",\"Entity/Delivery.php\",\"Entity/Message.php\",\"Entity/RateLimit.php\",\"Entity/SupportEvent.php\",\"Entity/Ticket.php\",\"Listener/SourcePageContext.php\",\"Notification/AlertConsumer.php\",\"Notification/DeliveryGate.php\",\"Notification/Dispatcher.php\",\"Notification/EmailConsumer.php\",\"Notification/EntityDeliveryGate.php\",\"Notification/EventDispatcher.php\",\"Notification/Policy.php\",\"Notification/RecipientKey.php\",\"Pub/Controller/AccountSupport.php\",\"Pub/Controller/Pwa.php\",\"Pub/Controller/StaffSupport.php\",\"Pub/Controller/Support.php\",\"Pub/View/PwaServiceWorker.php\",\"Repository/Message.php\",\"Repository/Ticket.php\",\"Security/GuestTicketSession.php\",\"Security/TicketAccess.php\",\"Service/GuestScreenshotService.php\",\"Service/GuestTicketCreateAttachmentFlow.php\",\"Service/RateLimiter.php\",\"Service/SourceContextResolver.php\",\"Service/Ticket/Creator.php\",\"Service/Ticket/Reply.php\",\"Service/Ticket/StaffUpdate.php\",\"Setup.php\",\"Util/GuestToken.php\",\"Util/PublicRef.php\",\"Util/RateKey.php\",\"Util/SafeContext.php\",\"Util/SiteConfig.php\",\"Util/StatusPolicy.php\",\"_data/code_event_listeners.xml\",\"_data/content_type_fields.xml\",\"_data/option_groups.xml\",\"_data/options.xml\",\"_data/permission_interface_groups.xml\",\"_data/permissions.xml\",\"_data/phrases.xml\",\"_data/routes.xml\",\"_data/template_modifications.xml\",\"_data/templates.xml\",\"addon.json\",\"hashes.json\"],\"targets\":{\"Notification/AlertConsumer.php\":{\"line_count\":74,\"matched_context\":[{\"sep\":true},{\"line\":1,\"text\":\"<?php\"},{\"line\":2,\"text\":\"\"},{\"line\":3,\"text\":\"namespace Gram\\\\Support\\\\Notification;\"},{\"line\":4,\"text\":\"\"},{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\SupportEvent;\"},{\"line\":6,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":7,\"text\":\"use XF\\\\Entity\\\\User;\"},{\"line\":8,\"text\":\"\"},{\"line\":9,\"text\":\"final class AlertConsumer\"},{\"line\":10,\"text\":\"{\"},{\"line\":11,\"text\":\" private DeliveryGate $gate;\"},{\"line\":12,\"text\":\"\"},{\"line\":13,\"text\":\" public function __construct(DeliveryGate $gate)\"},{\"line\":14,\"text\":\" {\"},{\"line\":15,\"text\":\" $this->gate = $gate;\"},{\"line\":16,\"text\":\" }\"},{\"line\":17,\"text\":\"\"},{\"line\":18,\"text\":\" public function consumeForUser(SupportEvent $event, Ticket $ticket, User $recipient): bool\"},{\"line\":19,\"text\":\" {\"},{\"line\":20,\"text\":\" if (!Policy::mayEmitExternal($event) || !$recipient->user_id)\"},{\"line\":21,\"text\":\" {\"},{\"line\":22,\"text\":\" return false;\"},{\"line\":23,\"text\":\" }\"},{\"line\":24,\"text\":\"\"},{\"line\":25,\"text\":\" // Never alert a user about a ticket they cannot access.\"},{\"line\":26,\"text\":\" $isOwner = $ticket->user_id && (int)$ticket->user_id === (int)$recipient->user_id;\"},{\"line\":27,\"text\":\" $isStaff = $recipient->hasPermission('gramSupport', 'viewAll')\"},{\"line\":28,\"text\":\" || $recipient->hasPermission('gramSupport', 'manage');\"},{\"line\":29,\"text\":\"\"},{\"line\":30,\"text\":\" if (!$isOwner && !$isStaff)\"},{\"line\":31,\"text\":\" {\"},{\"line\":32,\"text\":\" return false;\"},{\"line\":33,\"text\":\" }\"},{\"line\":34,\"text\":\"\"},{\"line\":35,\"text\":\" $recipientKey = RecipientKey::user((int)$recipient->user_id);\"},{\"line\":36,\"text\":\" if (!$this->gate->acquire((int)$event->event_id, 'xf_alert', $recipientKey))\"},{\"line\":37,\"text\":\" {\"},{\"line\":38,\"text\":\" return false;\"},{\"line\":39,\"text\":\" }\"},{\"line\":40,\"text\":\"\"},{\"line\":41,\"text\":\" try\"},{\"line\":42,\"text\":\" {\"},{\"line\":43,\"text\":\" /** @var \\\\XF\\\\Repository\\\\UserAlertRepository $alerts */\"},{\"line\":44,\"text\":\" $alerts = \\\\XF::repository('XF:UserAlert');\"},{\"line\":45,\"text\":\"\"},{\"line\":46,\"text\":\" // Back the alert with the recipient's own User content so the\"},{\"line\":47,\"text\":\" // core alert handler remains valid/viewable. Ticket access is\"},{\"line\":48,\"text\":\" // separately enforced before emission and again on ticket route.\"},{\"line\":49,\"text\":\" $alerts->alert(\"},{\"line\":50,\"text\":\" $recipient,\"},{\"line\":51,\"text\":\" 0,\"},{\"line\":52,\"text\":\" 'Support',\"},{\"line\":53,\"text\":\" 'user',\"},{\"line\":54,\"text\":\" (int)$recipient->user_id,\"},{\"line\":55,\"text\":\" 'gram_support_evt',\"},{\"line\":56,\"text\":\" Policy::alertExtraData($event),\"},{\"line\":57,\"text\":\" ['usePush' => false]\"},{\"line\":58,\"text\":\" );\"},{\"line\":59,\"text\":\"\"},{\"line\":60,\"text\":\" $this->gate->markSent((int)$event->event_id, 'xf_alert', $recipientKey);\"},{\"line\":61,\"text\":\" return true;\"},{\"line\":62,\"text\":\" }\"},{\"line\":63,\"text\":\" catch (\\\\Throwable $e)\"},{\"line\":64,\"text\":\" {\"},{\"line\":65,\"text\":\" $this->gate->markFailed(\"},{\"line\":66,\"text\":\" (int)$event->event_id,\"},{\"line\":67,\"text\":\" 'xf_alert',\"},{\"line\":68,\"text\":\" $recipientKey,\"},{\"line\":69,\"text\":\" get_class($e)\"},{\"line\":70,\"text\":\" );\"},{\"line\":71,\"text\":\" throw $e;\"},{\"line\":72,\"text\":\" }\"}],\"present\":true,\"sha256\":\"e22d0cdb0a0806c6a231504409bd17cd781caab0f28181aff7246b0295d8cd98\"},\"Notification/Dispatcher.php\":{\"line_count\":67,\"matched_context\":[{\"sep\":true},{\"line\":1,\"text\":\"<?php\"},{\"line\":2,\"text\":\"\"},{\"line\":3,\"text\":\"namespace Gram\\\\Support\\\\Notification;\"},{\"line\":4,\"text\":\"\"},{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\SupportEvent;\"},{\"line\":6,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":7,\"text\":\"use XF\\\\Entity\\\\User;\"},{\"line\":8,\"text\":\"\"},{\"line\":9,\"text\":\"final class Dispatcher\"},{\"line\":10,\"text\":\"{\"},{\"line\":11,\"text\":\" private AlertConsumer $alerts;\"},{\"line\":12,\"text\":\" private EmailConsumer $email;\"},{\"line\":13,\"text\":\"\"},{\"line\":14,\"text\":\" public function __construct(AlertConsumer $alerts, EmailConsumer $email)\"},{\"line\":15,\"text\":\" {\"},{\"line\":16,\"text\":\" $this->alerts = $alerts;\"},{\"line\":17,\"text\":\" $this->email = $email;\"},{\"line\":18,\"text\":\" }\"},{\"line\":19,\"text\":\"\"},{\"line\":20,\"text\":\" /**\"},{\"line\":21,\"text\":\" * Owner-facing delivery. Staff alert fan-out is intentionally provided by\"},{\"line\":22,\"text\":\" * dispatchStaff() so staff recipients must still pass Gram Support ACL.\"},{\"line\":23,\"text\":\" */\"},{\"line\":24,\"text\":\" public function dispatchOwner(SupportEvent $event, Ticket $ticket, ?User $owner): void\"},{\"line\":25,\"text\":\" {\"},{\"line\":26,\"text\":\" if (!Policy::mayEmitExternal($event))\"},{\"line\":27,\"text\":\" {\"},{\"line\":28,\"text\":\" return;\"},{\"line\":29,\"text\":\" }\"},{\"line\":30,\"text\":\"\"},{\"line\":31,\"text\":\" if ($owner && $owner->user_id)\"},{\"line\":32,\"text\":\" {\"},{\"line\":33,\"text\":\" $this->alerts->consumeForUser($event, $ticket, $owner);\"},{\"line\":34,\"text\":\" $this->email->consumeForRegistered($event, $ticket, $owner);\"},{\"line\":35,\"text\":\" return;\"},{\"line\":36,\"text\":\" }\"},{\"line\":37,\"text\":\"\"},{\"line\":38,\"text\":\" $this->email->consumeForGuest($event, $ticket);\"},{\"line\":39,\"text\":\" }\"},{\"line\":40,\"text\":\"\"},{\"line\":41,\"text\":\" /**\"},{\"line\":42,\"text\":\" * @param User[] $staffUsers\"},{\"line\":43,\"text\":\" */\"},{\"line\":44,\"text\":\" public function dispatchStaff(SupportEvent $event, Ticket $ticket, array $staffUsers): void\"},{\"line\":45,\"text\":\" {\"},{\"line\":46,\"text\":\" if (!Policy::mayEmitExternal($event))\"},{\"line\":47,\"text\":\" {\"},{\"line\":48,\"text\":\" return;\"},{\"line\":49,\"text\":\" }\"},{\"line\":50,\"text\":\"\"},{\"line\":51,\"text\":\" foreach ($staffUsers as $staff)\"},{\"line\":52,\"text\":\" {\"},{\"line\":53,\"text\":\" if (!$staff instanceof User || !$staff->user_id)\"},{\"line\":54,\"text\":\" {\"},{\"line\":55,\"text\":\" continue;\"},{\"line\":56,\"text\":\" }\"},{\"line\":57,\"text\":\"\"},{\"line\":58,\"text\":\" if (!$staff->hasPermission('gramSupport', 'viewAll')\"},{\"line\":59,\"text\":\" && !$staff->hasPermission('gramSupport', 'manage'))\"},{\"line\":60,\"text\":\" {\"},{\"line\":61,\"text\":\" continue;\"},{\"line\":62,\"text\":\" }\"},{\"line\":63,\"text\":\"\"},{\"line\":64,\"text\":\" $this->alerts->consumeForUser($event, $ticket, $staff);\"},{\"line\":65,\"text\":\" }\"},{\"line\":66,\"text\":\" }\"},{\"line\":67,\"text\":\"}\"}],\"present\":true,\"sha256\":\"a043d94bc91feeed0969ad218566cebac76b2d804e7c69cc2b87b94d42f5bb85\"},\"Pub/Controller/Support.php\":{\"line_count\":236,\"matched_context\":[{\"sep\":true},{\"line\":1,\"text\":\"<?php\"},{\"line\":2,\"text\":\"\"},{\"line\":3,\"text\":\"namespace Gram\\\\Support\\\\Pub\\\\Controller;\"},{\"line\":4,\"text\":\"\"},{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Notification\\\\EventDispatcher;\"},{\"line\":6,\"text\":\"use Gram\\\\Support\\\\Security\\\\GuestTicketSession;\"},{\"line\":7,\"text\":\"use Gram\\\\Support\\\\Security\\\\TicketAccess;\"},{\"line\":8,\"text\":\"use Gram\\\\Support\\\\Service\\\\GuestTicketCreateAttachmentFlow;\"},{\"line\":9,\"text\":\"use Gram\\\\Support\\\\Service\\\\RateLimiter;\"},{\"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\":\"{\"},{\"sep\":true},{\"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');\"},{\"line\":41,\"text\":\" $category = $this->filter('category', 'str');\"},{\"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(\"},{\"line\":57,\"text\":\" SiteConfig::siteId(),\"},{\"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)\"},{\"sep\":true},{\"line\":74,\"text\":\" if ($upload)\"},{\"line\":75,\"text\":\" {\"},{\"line\":76,\"text\":\" $attachmentId = $attachmentFlow->prepare($upload, $tempHash);\"},{\"line\":77,\"text\":\" }\"},{\"line\":78,\"text\":\"\"},{\"line\":79,\"text\":\" /** @var Creator $creator */\"},{\"line\":80,\"text\":\" $creator = $this->service(Creator::class);\"},{\"line\":81,\"text\":\" $created = $creator->create([\"},{\"line\":82,\"text\":\" 'email' => $email,\"},{\"line\":83,\"text\":\" 'category' => $category,\"},{\"line\":84,\"text\":\" 'subject' => $subject,\"},{\"line\":85,\"text\":\" 'message' => $message\"},{\"line\":86,\"text\":\" ]);\"},{\"line\":87,\"text\":\"\"},{\"sep\":true},{\"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\":\" {\"},{\"sep\":true},{\"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))\"},{\"sep\":true},{\"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\":\" }\"}],\"present\":true,\"sha256\":\"6cb34b1d27e9f0132263637cefa62fe0e998a9a86620b7ac33199f41ee86f9d4\"},\"Service/Ticket/Creator.php\":{\"line_count\":139,\"matched_context\":[{\"sep\":true},{\"line\":8,\"text\":\"use Gram\\\\Support\\\\Util\\\\PublicRef;\"},{\"line\":9,\"text\":\"use Gram\\\\Support\\\\Util\\\\SafeContext;\"},{\"line\":10,\"text\":\"use Gram\\\\Support\\\\Util\\\\SiteConfig;\"},{\"line\":11,\"text\":\"use Gram\\\\Support\\\\Util\\\\StatusPolicy;\"},{\"line\":12,\"text\":\"use XF\\\\Service\\\\AbstractService;\"},{\"line\":13,\"text\":\"use Gram\\\\Support\\\\Notification\\\\EventDispatcher;\"},{\"line\":14,\"text\":\"\"},{\"line\":15,\"text\":\"class Creator extends AbstractService\"},{\"line\":16,\"text\":\"{\"},{\"line\":17,\"text\":\" public function create(array $input, ?int $now = null): array\"},{\"line\":18,\"text\":\" {\"},{\"line\":19,\"text\":\" $now = $now ?? \\\\XF::$time;\"},{\"line\":20,\"text\":\" $visitor = \\\\XF::visitor();\"},{\"line\":21,\"text\":\" $siteId = SiteConfig::siteId();\"},{\"line\":22,\"text\":\"\"},{\"line\":23,\"text\":\" $email = strtolower(trim((string)($input['email'] ?? '')));\"},{\"line\":24,\"text\":\" $category = trim((string)($input['category'] ?? ''));\"},{\"line\":25,\"text\":\" $subject = trim((string)($input['subject'] ?? ''));\"},{\"line\":26,\"text\":\" $messageText = trim((string)($input['message'] ?? ''));\"},{\"line\":27,\"text\":\"\"},{\"line\":28,\"text\":\" if ($category === '' || $messageText === '')\"},{\"line\":29,\"text\":\" {\"},{\"line\":30,\"text\":\" throw new \\\\InvalidArgumentException('GRAM_SUPPORT_REQUIRED_FIELDS');\"},{\"line\":31,\"text\":\" }\"},{\"line\":32,\"text\":\"\"},{\"line\":33,\"text\":\" if (!$visitor->user_id && !filter_var($email, FILTER_VALIDATE_EMAIL))\"},{\"line\":34,\"text\":\" {\"},{\"line\":35,\"text\":\" throw new \\\\InvalidArgumentException('GRAM_SUPPORT_VALID_EMAIL_REQUIRED');\"},{\"line\":36,\"text\":\" }\"},{\"line\":37,\"text\":\"\"},{\"line\":38,\"text\":\" if ($subject === '')\"},{\"line\":39,\"text\":\" {\"},{\"line\":40,\"text\":\" $subject = function_exists('mb_substr')\"},{\"sep\":true},{\"line\":68,\"text\":\" /** @var Ticket $ticket */\"},{\"line\":69,\"text\":\" $ticket = $this->em()->create('Gram\\\\Support:Ticket');\"},{\"line\":70,\"text\":\" $ticket->public_ref = 'TMP-' . bin2hex(random_bytes(12));\"},{\"line\":71,\"text\":\" $ticket->site_id = $siteId;\"},{\"line\":72,\"text\":\" $ticket->user_id = (int)$visitor->user_id;\"},{\"line\":73,\"text\":\" $ticket->guest_email = $visitor->user_id ? '' : $email;\"},{\"line\":74,\"text\":\" $ticket->guest_access_token_hash = $guest ? $guest['hash'] : '';\"},{\"line\":75,\"text\":\" $ticket->guest_access_expires = $guest\"},{\"line\":76,\"text\":\" ? $now + SiteConfig::guestTokenTtlSeconds()\"},{\"line\":77,\"text\":\" : 0;\"},{\"line\":78,\"text\":\" $ticket->node_id = (int)($context['node_id'] ?? 0);\"},{\"sep\":true},{\"line\":96,\"text\":\" $ticket->save();\"},{\"line\":97,\"text\":\"\"},{\"line\":98,\"text\":\" $message = $this->em()->create('Gram\\\\Support:Message');\"},{\"line\":99,\"text\":\" $message->ticket_id = (int)$ticket->ticket_id;\"},{\"line\":100,\"text\":\" $message->user_id = (int)$visitor->user_id;\"},{\"line\":101,\"text\":\" $message->is_staff = 0;\"},{\"line\":102,\"text\":\" $message->is_internal = 0;\"},{\"line\":103,\"text\":\" $message->message = $messageText;\"},{\"line\":104,\"text\":\" $message->message_date = $now;\"},{\"line\":105,\"text\":\" $message->save();\"},{\"line\":106,\"text\":\"\"},{\"line\":107,\"text\":\" $ticket->last_message_id = (int)$message->message_id;\"},{\"line\":108,\"text\":\" $ticket->save();\"},{\"line\":109,\"text\":\"\"},{\"line\":110,\"text\":\" $event = $this->em()->create('Gram\\\\Support:SupportEvent');\"},{\"line\":111,\"text\":\" $event->ticket_id = (int)$ticket->ticket_id;\"},{\"line\":112,\"text\":\" $event->site_id = $siteId;\"},{\"line\":113,\"text\":\" $event->actor_user_id = (int)$visitor->user_id;\"},{\"line\":114,\"text\":\" $event->event_type = 'ticket_created';\"},{\"line\":115,\"text\":\" $event->event_date = $now;\"},{\"line\":116,\"text\":\" $event->safe_payload_json = json_encode([\"},{\"line\":117,\"text\":\" 'public_ref' => (string)$ticket->public_ref,\"},{\"line\":118,\"text\":\" 'category' => (string)$ticket->category,\"},{\"line\":119,\"text\":\" 'is_internal' => false\"},{\"sep\":true},{\"line\":126,\"text\":\" {\"},{\"line\":127,\"text\":\" $db->rollback();\"},{\"line\":128,\"text\":\" throw $e;\"},{\"line\":129,\"text\":\" }\"},{\"line\":130,\"text\":\"\"},{\"line\":131,\"text\":\" (new EventDispatcher())->dispatchSafely($event, $ticket);\"},{\"line\":132,\"text\":\"\"},{\"line\":133,\"text\":\" return [\"},{\"line\":134,\"text\":\" 'ticket' => $ticket,\"},{\"line\":135,\"text\":\" 'event' => $event,\"},{\"line\":136,\"text\":\" 'guest_secret' => $guest ? $guest['secret'] : null\"}],\"present\":true,\"sha256\":\"7a84cd77761a7943495f9d3ef11269987f85265170ad6cf927a1661b8bf0a99a\"},\"Service/Ticket/Reply.php\":{\"line_count\":68,\"matched_context\":[{\"sep\":true},{\"line\":3,\"text\":\"namespace Gram\\\\Support\\\\Service\\\\Ticket;\"},{\"line\":4,\"text\":\"\"},{\"line\":5,\"text\":\"use Gram\\\\Support\\\\Entity\\\\Ticket;\"},{\"line\":6,\"text\":\"use Gram\\\\Support\\\\Util\\\\SiteConfig;\"},{\"line\":7,\"text\":\"use XF\\\\Service\\\\AbstractService;\"},{\"line\":8,\"text\":\"use Gram\\\\Support\\\\Notification\\\\EventDispatcher;\"},{\"line\":9,\"text\":\"\"},{\"line\":10,\"text\":\"class Reply extends AbstractService\"},{\"line\":11,\"text\":\"{\"},{\"line\":12,\"text\":\" public function add(Ticket $ticket, string $messageText, bool $isStaff, bool $isInternal = false): array\"},{\"line\":13,\"text\":\" {\"},{\"line\":14,\"text\":\" $messageText = trim($messageText);\"},{\"line\":15,\"text\":\" if ($messageText === '')\"},{\"line\":16,\"text\":\" {\"},{\"line\":17,\"text\":\" throw new \\\\InvalidArgumentException('GRAM_SUPPORT_EMPTY_REPLY');\"},{\"line\":18,\"text\":\" }\"},{\"line\":19,\"text\":\" if ($isInternal && !$isStaff)\"},{\"line\":20,\"text\":\" {\"},{\"line\":21,\"text\":\" throw new \\\\LogicException('INTERNAL_REQUIRES_STAFF');\"},{\"line\":22,\"text\":\" }\"},{\"line\":23,\"text\":\"\"},{\"line\":24,\"text\":\" $visitor = \\\\XF::visitor();\"},{\"line\":25,\"text\":\" $now = \\\\XF::$time;\"},{\"line\":26,\"text\":\" $db = \\\\XF::db();\"},{\"sep\":true},{\"line\":29,\"text\":\" try\"},{\"line\":30,\"text\":\" {\"},{\"line\":31,\"text\":\" $message = $this->em()->create('Gram\\\\Support:Message');\"},{\"line\":32,\"text\":\" $message->ticket_id = (int)$ticket->ticket_id;\"},{\"line\":33,\"text\":\" $message->user_id = (int)$visitor->user_id;\"},{\"line\":34,\"text\":\" $message->is_staff = $isStaff ? 1 : 0;\"},{\"line\":35,\"text\":\" $message->is_internal = $isInternal ? 1 : 0;\"},{\"line\":36,\"text\":\" $message->message = $messageText;\"},{\"line\":37,\"text\":\" $message->message_date = $now;\"},{\"line\":38,\"text\":\" $message->save();\"},{\"line\":39,\"text\":\"\"},{\"line\":40,\"text\":\" $ticket->last_message_id = (int)$message->message_id;\"},{\"line\":41,\"text\":\" $ticket->updated_date = $now;\"},{\"line\":42,\"text\":\" $ticket->save();\"},{\"line\":43,\"text\":\"\"},{\"line\":44,\"text\":\" $event = $this->em()->create('Gram\\\\Support:SupportEvent');\"},{\"line\":45,\"text\":\" $event->ticket_id = (int)$ticket->ticket_id;\"},{\"line\":46,\"text\":\" $event->site_id = (string)$ticket->site_id;\"},{\"line\":47,\"text\":\" $event->actor_user_id = (int)$visitor->user_id;\"},{\"line\":48,\"text\":\" $event->event_type = $isInternal ? 'internal_note_created' : 'ticket_reply_created';\"},{\"line\":49,\"text\":\" $event->event_date = $now;\"},{\"line\":50,\"text\":\" $event->safe_payload_json = json_encode([\"},{\"line\":51,\"text\":\" 'public_ref' => (string)$ticket->public_ref,\"},{\"line\":52,\"text\":\" 'is_internal' => $isInternal\"},{\"line\":53,\"text\":\" ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);\"},{\"sep\":true},{\"line\":59,\"text\":\" {\"},{\"line\":60,\"text\":\" $db->rollback();\"},{\"line\":61,\"text\":\" throw $e;\"},{\"line\":62,\"text\":\" }\"},{\"line\":63,\"text\":\"\"},{\"line\":64,\"text\":\" (new EventDispatcher())->dispatchSafely($event, $ticket);\"},{\"line\":65,\"text\":\"\"},{\"line\":66,\"text\":\" return ['message' => $message, 'event' => $event];\"},{\"line\":67,\"text\":\" }\"},{\"line\":68,\"text\":\"}\"}],\"present\":true,\"sha256\":\"482571a2ccf07a3c8672f34940243264a8271ef8c3cbc4fadbb46112afd36830\"},\"_data/templates.xml\":{\"line_count\":781,\"matched_context\":[{\"sep\":true},{\"line\":1,\"text\":\"<?xml version='1.0' encoding='utf-8'?>\"},{\"line\":2,\"text\":\"<templates>\"},{\"line\":3,\"text\":\" <template type=\\\"public\\\" title=\\\"alert_user_gram_support_evt\\\" version_id=\\\"1000050\\\" version_string=\\\"1.0.0 Alpha 3 Unified Fix 3\\\">&lt;xf:macro id=\\\"content\\\"&gt;\"},{\"line\":4,\"text\":\"\\t{{ phrase('gram_support_alert_ticket_event', {\"},{\"line\":5,\"text\":\"\\t\\t'public_ref': $alert.extra_data.public_ref\"},{\"line\":6,\"text\":\"\\t}) }}\"},{\"line\":7,\"text\":\"&lt;/xf:macro&gt;\"},{\"line\":8,\"text\":\"</template>\"},{\"line\":9,\"text\":\" <template type=\\\"public\\\" title=\\\"gram_support.less\\\" version_id=\\\"1000100\\\" version_string=\\\"1.0.0 Alpha 3 Unified Fix 8\\\">.gramSupport-launcher\"},{\"line\":10,\"text\":\"{\"},{\"sep\":true},{\"line\":490,\"text\":\"\"},{\"line\":491,\"text\":\"&lt;xf:form action=\\\"{{ link('support/create') }}\\\" method=\\\"post\\\" upload=\\\"true\\\" class=\\\"block\\\"&gt;\"},{\"line\":492,\"text\":\"\\t&lt;div class=\\\"block-container\\\"&gt;\"},{\"line\":493,\"text\":\"\\t\\t&lt;div class=\\\"block-body\\\"&gt;\"},{\"line\":494,\"text\":\"\\t\\t\\t&lt;xf:if is=\\\"!$xf.visitor.user_id\\\"&gt;\"},{\"line\":495,\"text\":\"\\t\\t\\t\\t&lt;xf:textboxrow name=\\\"email\\\" type=\\\"email\\\" required=\\\"required\\\"\"},{\"line\":496,\"text\":\"\\t\\t\\t\\t\\tlabel=\\\"{{ phrase('email') }}\\\" /&gt;\"},{\"line\":497,\"text\":\"\\t\\t\\t&lt;/xf:if&gt;\"},{\"line\":498,\"text\":\"\\t\\t\\t&lt;xf:selectrow name=\\\"category\\\" required=\\\"required\\\"\"},{\"line\":499,\"text\":\"\\t\\t\\t\\tlabel=\\\"{{ phrase('gram_support_category') }}\\\"&gt;\"},{\"line\":500,\"text\":\"\\t\\t\\t\\t&lt;xf:option value=\\\"technical\\\"&gt;{{ phrase('gram_support_category_technical') }}&lt;/xf:option&gt;\"},{\"line\":501,\"text\":\"\\t\\t\\t\\t&lt;xf:option value=\\\"account\\\"&gt;{{ phrase('gram_support_category_account') }}&lt;/xf:option&gt;\"},{\"sep\":true},{\"line\":507,\"text\":\"\\t\\t\\t&lt;xf:textarearow name=\\\"message\\\" required=\\\"required\\\" rows=\\\"8\\\"\"},{\"line\":508,\"text\":\"\\t\\t\\t\\tlabel=\\\"{{ phrase('gram_support_description') }}\\\" /&gt;\"},{\"line\":509,\"text\":\"\\t\\t\\t&lt;xf:uploadrow name=\\\"screenshot\\\" accept=\\\".gif,.jpeg,.jpg,.jpe,.png,.webp\\\"\"},{\"line\":510,\"text\":\"\\t\\t\\t\\tlabel=\\\"{{ phrase('gram_support_screenshot_optional') }}\\\" /&gt;\"},{\"line\":511,\"text\":\"\\t\\t\\t&lt;xf:if is=\\\"!$xf.visitor.user_id\\\"&gt;\"},{\"line\":512,\"text\":\"\\t\\t\\t\\t&lt;xf:captcharow label=\\\"{{ phrase('verification') }}\\\"\"},{\"line\":513,\"text\":\"\\t\\t\\t\\t\\thint=\\\"{{ phrase('required') }}\\\" force=\\\"true\\\" /&gt;\"},{\"line\":514,\"text\":\"\\t\\t\\t&lt;/xf:if&gt;\"},{\"line\":515,\"text\":\"\\t\\t&lt;/div&gt;\"},{\"line\":516,\"text\":\"\\t\\t&lt;xf:submitrow submit=\\\"{{ phrase('gram_support_submit') }}\\\" /&gt;\"},{\"line\":517,\"text\":\"\\t&lt;/div&gt;\"},{\"sep\":true},{\"line\":548,\"text\":\"\\t\\taria-label=\\\"{{ phrase('gram_support_open_support') }}\\\"&gt;\"},{\"line\":549,\"text\":\"\\t\\t{{ phrase('gram_support_open_support') }}\"},{\"line\":550,\"text\":\"\\t&lt;/a&gt;\"},{\"line\":551,\"text\":\"&lt;/xf:if&gt;\"},{\"line\":552,\"text\":\"</template>\"},{\"line\":553,\"text\":\" <template type=\\\"public\\\" title=\\\"gram_support_staff_queue\\\" version_id=\\\"1000050\\\" version_string=\\\"1.0.0 Alpha 3 Unified Fix 3\\\">&lt;xf:title&gt;{{ phrase('gram_support_staff_queue') }}&lt;/xf:title&gt;\"},{\"line\":554,\"text\":\"&lt;xf:css src=\\\"gram_support.less\\\" /&gt;\"},{\"line\":555,\"text\":\"&lt;span class=\\\"js-gramSupportPwaConfig\\\" hidden\"},{\"line\":556,\"text\":\"\\tdata-manifest-url=\\\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\\\"\"},{\"line\":557,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"&gt;&lt;/span&gt;\"},{\"line\":558,\"text\":\"&lt;xf:js addon=\\\"Gram/Support\\\" src=\\\"gram/support/staff-pwa.js\\\" min=\\\"1\\\" /&gt;\"},{\"line\":559,\"text\":\"\"},{\"line\":560,\"text\":\"&lt;div class=\\\"block\\\"&gt;\"},{\"line\":561,\"text\":\"\\t&lt;div class=\\\"block-container\\\"&gt;\"},{\"line\":562,\"text\":\"\\t\\t&lt;div class=\\\"block-body\\\"&gt;\"},{\"line\":563,\"text\":\"\\t\\t\\t&lt;xf:foreach loop=\\\"$tickets\\\" value=\\\"$ticket\\\"&gt;\"},{\"line\":564,\"text\":\"\\t\\t\\t\\t&lt;div class=\\\"block-row\\\"&gt;\"},{\"line\":565,\"text\":\"\\t\\t\\t\\t\\t&lt;a href=\\\"{{ link('support/staff/ticket', null, {'ref': $ticket.public_ref}) }}\\\"&gt;\"},{\"line\":566,\"text\":\"\\t\\t\\t\\t\\t\\t{{ $ticket.public_ref }} \\u2014 {{ $ticket.subject }}\"},{\"line\":567,\"text\":\"\\t\\t\\t\\t\\t&lt;/a&gt;\"},{\"line\":568,\"text\":\"\\t\\t\\t\\t\\t&lt;span class=\\\"u-muted\\\"&gt;{{ $ticket.status }}&lt;/span&gt;\"},{\"line\":569,\"text\":\"\\t\\t\\t\\t&lt;/div&gt;\"},{\"line\":570,\"text\":\"\\t\\t\\t&lt;/xf:foreach&gt;\"},{\"line\":571,\"text\":\"\\t\\t&lt;/div&gt;\"},{\"line\":572,\"text\":\"\\t&lt;/div&gt;\"},{\"line\":573,\"text\":\"&lt;/div&gt;\"},{\"line\":574,\"text\":\"</template>\"},{\"line\":575,\"text\":\" <template type=\\\"public\\\" title=\\\"gram_support_staff_service_worker\\\" version_id=\\\"1000050\\\" version_string=\\\"1.0.0 Alpha 3 Unified Fix 3\\\">'use strict';\"},{\"line\":576,\"text\":\"\"},{\"line\":577,\"text\":\"const OFFLINE_URL = '{{ base_url('js/gram/support/pwa/offline.html')|escape('js') }}';\"},{\"line\":578,\"text\":\"const STATIC_CACHE = 'gram-support-staff-static-v1';\"},{\"line\":579,\"text\":\"\"},{\"line\":580,\"text\":\"self.addEventListener('install', event =&gt; {\"},{\"line\":581,\"text\":\"\\tevent.waitUntil(\"},{\"line\":582,\"text\":\"\\t\\tcaches.open(STATIC_CACHE)\"},{\"line\":583,\"text\":\"\\t\\t\\t.then(cache =&gt; cache.addAll([OFFLINE_URL]))\"},{\"sep\":true},{\"line\":587,\"text\":\"\"},{\"line\":588,\"text\":\"self.addEventListener('activate', event =&gt; {\"},{\"line\":589,\"text\":\"\\tevent.waitUntil(\"},{\"line\":590,\"text\":\"\\t\\tcaches.keys().then(keys =&gt;\"},{\"line\":591,\"text\":\"\\t\\t\\tPromise.all(keys\"},{\"line\":592,\"text\":\"\\t\\t\\t\\t.filter(key =&gt; key.startsWith('gram-support-staff-static-') &amp;&amp; key !== STATIC_CACHE)\"},{\"line\":593,\"text\":\"\\t\\t\\t\\t.map(key =&gt; caches.delete(key))\"},{\"line\":594,\"text\":\"\\t\\t\\t)\"},{\"line\":595,\"text\":\"\\t\\t).then(() =&gt; self.clients.claim())\"},{\"line\":596,\"text\":\"\\t);\"},{\"line\":597,\"text\":\"});\"},{\"sep\":true},{\"line\":607,\"text\":\"\\t\\treturn;\"},{\"line\":608,\"text\":\"\\t}\"},{\"line\":609,\"text\":\"\"},{\"line\":610,\"text\":\"\\t// SECURITY: all support/ticket/account/admin-like content is network-only.\"},{\"line\":611,\"text\":\"\\t// Never cache HTML/API responses that can contain ticket data, identities,\"},{\"line\":612,\"text\":\"\\t// access state, internal notes, attachments or staff-only information.\"},{\"line\":613,\"text\":\"\\tconst sensitive =\"},{\"line\":614,\"text\":\"\\t\\turl.pathname.startsWith('/support/') ||\"},{\"line\":615,\"text\":\"\\t\\turl.pathname.startsWith('/account/') ||\"},{\"line\":616,\"text\":\"\\t\\turl.pathname.startsWith('/admin.php') ||\"},{\"line\":617,\"text\":\"\\t\\trequest.headers.get('accept')?.includes('text/html');\"},{\"sep\":true},{\"line\":642,\"text\":\"\\t\\t\\t})\"},{\"line\":643,\"text\":\"\\t\\t)\"},{\"line\":644,\"text\":\"\\t);\"},{\"line\":645,\"text\":\"});\"},{\"line\":646,\"text\":\"</template>\"},{\"line\":647,\"text\":\" <template type=\\\"public\\\" title=\\\"gram_support_staff_ticket\\\" version_id=\\\"1000050\\\" version_string=\\\"1.0.0 Alpha 3 Unified Fix 3\\\">&lt;xf:title&gt;{{ phrase('gram_support_staff_ticket') }} {{ $ticket.public_ref }}&lt;/xf:title&gt;\"},{\"line\":648,\"text\":\"&lt;xf:css src=\\\"gram_support.less\\\" /&gt;\"},{\"line\":649,\"text\":\"&lt;span class=\\\"js-gramSupportPwaConfig\\\" hidden\"},{\"line\":650,\"text\":\"\\tdata-manifest-url=\\\"{{ base_url('js/gram/support/pwa/manifest.webmanifest') }}\\\"\"},{\"line\":651,\"text\":\"\\tdata-sw-url=\\\"{{ link('support/service-worker') }}\\\"&gt;&lt;/span&gt;\"},{\"line\":652,\"text\":\"&lt;xf:js addon=\\\"Gram/Support\\\" src=\\\"gram/support/staff-pwa.js\\\" min=\\\"1\\\" /&gt;\"},{\"line\":653,\"text\":\"\"},{\"line\":654,\"text\":\"&lt;div class=\\\"block\\\"&gt;\"},{\"line\":655,\"text\":\"\\t&lt;div class=\\\"block-container\\\"&gt;\"},{\"line\":656,\"text\":\"\\t\\t&lt;h2 class=\\\"block-header\\\"&gt;{{ $ticket.public_ref }} \\u2014 {{ $ticket.subject }}&lt;/h2&gt;\"},{\"line\":657,\"text\":\"\\t\\t&lt;div class=\\\"block-body\\\"&gt;\"},{\"sep\":true},{\"line\":682,\"text\":\"\\t\\t\\t&lt;/div&gt;\"},{\"line\":683,\"text\":\"\\t\\t&lt;/div&gt;\"},{\"line\":684,\"text\":\"\\t&lt;/div&gt;\"},{\"line\":685,\"text\":\"&lt;/xf:if&gt;\"},{\"line\":686,\"text\":\"\"},{\"line\":687,\"text\":\"&lt;xf:form action=\\\"{{ link('support/staff/reply', null, {'ref': $ticket.public_ref}) }}\\\" method=\\\"post\\\" class=\\\"block\\\"&gt;\"},{\"line\":688,\"text\":\"\\t&lt;div class=\\\"block-container\\\"&gt;\"},{\"line\":689,\"text\":\"\\t\\t&lt;div class=\\\"block-body\\\"&gt;\"},{\"line\":690,\"text\":\"\\t\\t\\t&lt;xf:textarearow name=\\\"message\\\" required=\\\"required\\\" rows=\\\"6\\\" label=\\\"{{ phrase('gram_support_reply') }}\\\" /&gt;\"},{\"line\":691,\"text\":\"\\t\\t\\t&lt;xf:if is=\\\"$xf.visitor.hasPermission('gramSupport', 'internalNotes')\\\"&gt;\"},{\"line\":692,\"text\":\"\\t\\t\\t\\t&lt;xf:checkboxrow&gt;\"},{\"line\":693,\"text\":\"\\t\\t\\t\\t\\t&lt;xf:option name=\\\"is_internal\\\" value=\\\"1\\\"&gt;{{ phrase('gram_support_internal_note') }}&lt;/xf:option&gt;\"},{\"line\":694,\"text\":\"\\t\\t\\t\\t&lt;/xf:checkboxrow&gt;\"},{\"line\":695,\"text\":\"\\t\\t\\t&lt;/xf:if&gt;\"},{\"line\":696,\"text\":\"\\t\\t&lt;/div&gt;\"},{\"line\":697,\"text\":\"\\t\\t&lt;xf:submitrow submit=\\\"{{ phrase('gram_support_send') }}\\\" /&gt;\"},{\"line\":698,\"text\":\"\\t&lt;/div&gt;\"},{\"line\":699,\"text\":\"&lt;/xf:form&gt;\"},{\"line\":700,\"text\":\"\"},{\"line\":701,\"text\":\"&lt;xf:form action=\\\"{{ link('support/staff/update', null, {'ref': $ticket.public_ref}) }}\\\" method=\\\"post\\\" class=\\\"block\\\"&gt;\"},{\"line\":702,\"text\":\"\\t&lt;div class=\\\"block-container\\\"&gt;\"},{\"line\":703,\"text\":\"\\t\\t&lt;div class=\\\"block-body\\\"&gt;\"},{\"line\":704,\"text\":\"\\t\\t\\t&lt;xf:selectrow name=\\\"status\\\" value=\\\"{$ticket.status}\\\" label=\\\"{{ phrase('gram_support_status') }}\\\"&gt;\"},{\"line\":705,\"text\":\"\\t\\t\\t\\t&lt;xf:foreach loop=\\\"$statusOptions\\\" value=\\\"$status\\\"&gt;\"},{\"line\":706,\"text\":\"\\t\\t\\t\\t\\t&lt;xf:option value=\\\"{$status}\\\"&gt;{$status}&lt;/xf:option&gt;\"},{\"sep\":true},{\"line\":748,\"text\":\"\\t\\t&lt;/div&gt;\"},{\"line\":749,\"text\":\"\\t&lt;/div&gt;\"},{\"line\":750,\"text\":\"&lt;/xf:if&gt;\"},{\"line\":751,\"text\":\"\"},{\"line\":752,\"text\":\"&lt;xf:if is=\\\"$ticket.status != 'CLOSED'\\\"&gt;\"},{\"line\":753,\"text\":\"\\t&lt;xf:form action=\\\"{{ link('support/reply', null, {'ref': $ticket.public_ref}) }}\\\" method=\\\"post\\\" class=\\\"block\\\"&gt;\"},{\"line\":754,\"text\":\"\\t\\t&lt;div class=\\\"block-container\\\"&gt;\"},{\"line\":755,\"text\":\"\\t\\t\\t&lt;div class=\\\"block-body\\\"&gt;\"},{\"line\":756,\"text\":\"\\t\\t\\t\\t&lt;xf:textarearow name=\\\"message\\\" required=\\\"required\\\" rows=\\\"6\\\"\"},{\"line\":757,\"text\":\"\\t\\t\\t\\t\\tlabel=\\\"{{ phrase('gram_support_reply') }}\\\" /&gt;\"},{\"line\":758,\"text\":\"\\t\\t\\t&lt;/div&gt;\"},{\"line\":759,\"text\":\"\\t\\t\\t&lt;xf:submitrow submit=\\\"{{ phrase('gram_support_send') }}\\\" /&gt;\"},{\"line\":760,\"text\":\"\\t\\t&lt;/div&gt;\"},{\"line\":761,\"text\":\"\\t&lt;/xf:form&gt;\"},{\"line\":762,\"text\":\"&lt;/xf:if&gt;\"},{\"line\":763,\"text\":\"</template>\"},{\"line\":764,\"text\":\" <template type=\\\"email\\\" title=\\\"gram_support_ticket_event\\\" version_id=\\\"1000050\\\" version_string=\\\"1.0.0 Alpha 3 Unified Fix 3\\\">&lt;mail:subject&gt;\"},{\"line\":765,\"text\":\"\\t{{ phrase('gram_support_email_ticket_event_subject', {'public_ref': $ticket.public_ref}) }}\"},{\"line\":766,\"text\":\"&lt;/mail:subject&gt;\"},{\"line\":767,\"text\":\"\"},{\"line\":768,\"text\":\"{{ phrase('gram_support_email_ticket_event_body_registered', {\"},{\"line\":769,\"text\":\"\\t'public_ref': $ticket.public_ref\"},{\"line\":770,\"text\":\"}) }}\"},{\"line\":771,\"text\":\"</template>\"},{\"line\":772,\"text\":\" <template type=\\\"email\\\" title=\\\"gram_support_ticket_event_guest\\\" version_id=\\\"1000050\\\" version_string=\\\"1.0.0 Alpha 3 Unified Fix 3\\\">&lt;mail:subject&gt;\"},{\"line\":773,\"text\":\"\\t{{ phrase('gram_support_email_ticket_event_subject', {'public_ref': $ticket.public_ref}) }}\"},{\"line\":774,\"text\":\"&lt;/mail:subject&gt;\"},{\"line\":775,\"text\":\"\"},{\"line\":776,\"text\":\"{{ phrase('gram_support_email_ticket_event_body_guest', {\"},{\"line\":777,\"text\":\"\\t'public_ref': $ticket.public_ref,\"},{\"line\":778,\"text\":\"\\t'access_url': $accessUrl\"},{\"line\":779,\"text\":\"}) }}\"},{\"line\":780,\"text\":\"</template>\"},{\"line\":781,\"text\":\"</templates>\"}],\"present\":true,\"sha256\":\"1a344bd306135486d2019bf0a5cafff5eb472882f7b3433ef13af4556a4c791e\"}}},\"transport_rc\":0,\"transport_stderr_bytes\":0,\"transport_stderr_sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"}\nGRAM516R1R3_NOTIFICATION_FILES=[\"Notification/AlertConsumer.php\",\"Notification/DeliveryGate.php\",\"Notification/Dispatcher.php\",\"Notification/EmailConsumer.php\",\"Notification/EntityDeliveryGate.php\",\"Notification/EventDispatcher.php\",\"Notification/Policy.php\",\"Notification/RecipientKey.php\"]\nGRAM516R1R3_EMAIL_CONSUMER_FILE_PRESENT=true\nGRAM516R1R3_DECISION=PASS_NOTIFY_CAPTCHA_SOURCE_EVIDENCE_CAPTURED\nGRAM516R1R3_NEXT_GATE=BUILD_EXACT_TURNSTILE_AND_EMAIL_NOTIFY_CHANGE\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260918-GRAM-SUPPORT-NOTIFY-CAPTCHA-SOURCE-READONLY-516R1R3\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n"
}