for (;;);{"error":null,"payload":{"timeline":"\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_93\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6382080\" id=\"6382080\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-pencil phui-timeline-icon\" data-meta=\"0_92\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_0\"\u003etstarling\u003c\/a\u003e created this task.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6382080\" data-sigil=\"has-tooltip\" data-meta=\"0_91\"\u003e\u003cspan class=\"screen-only\"\u003eAug 13 2020, 7:38 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-13 07:38:48 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_96\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/4vfodng5xaao26r6l2bf\/PHID-FILE-2gvu7et6e6bs2cswr2hw\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/Joe\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6382092\" id=\"6382092\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user-plus phui-timeline-icon\" data-meta=\"0_95\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/Joe\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_24\"\u003eJoe\u003c\/a\u003e added a subscriber: \u003ca href=\"\/p\/JMeybohm\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_25\"\u003eJMeybohm\u003c\/a\u003e.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6382092\" data-sigil=\"has-tooltip\" data-meta=\"0_94\"\u003e\u003cspan class=\"screen-only\"\u003eAug 13 2020, 7:39 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-13 07:39:41 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_99\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/mcdy6bokf2bfd6lhrj5x\/PHID-FILE-hvay22mxxy4ab7u76frl\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/Addshore\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6382118\" id=\"6382118\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user-plus phui-timeline-icon\" data-meta=\"0_98\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/Addshore\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_26\"\u003eAddshore\u003c\/a\u003e subscribed.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6382118\" data-sigil=\"has-tooltip\" data-meta=\"0_97\"\u003e\u003cspan class=\"screen-only\"\u003eAug 13 2020, 8:18 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-13 08:18:41 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_102\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6387703\" id=\"6387703\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-link phui-timeline-icon\" data-meta=\"0_101\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_27\"\u003etstarling\u003c\/a\u003e mentioned this in \u003ca href=\"\/T260504\" class=\"phui-handle\" data-sigil=\"hovercard\" data-meta=\"0_28\"\u003eT260504: Get rid of remaining non-Thumbor MediaWiki image scaling in WMF production\u003c\/a\u003e.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6387703\" data-sigil=\"has-tooltip\" data-meta=\"0_100\"\u003e\u003cspan class=\"screen-only\"\u003eAug 17 2020, 12:28 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-17 00:28:04 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell phui-timeline-green\" data-sigil=\"transaction anchor-container\" data-meta=\"0_105\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/c6xmpug7aawzqcut5d3f\/PHID-FILE-v2zy4knvlloiceegtfy7\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/fgiunchedi\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6388077\" id=\"6388077\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill fill-has-color phui-timeline-icon-fill-green\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-arrow-right phui-timeline-icon\" data-meta=\"0_104\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/fgiunchedi\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_29\"\u003efgiunchedi\u003c\/a\u003e triaged this task as \u003cspan class=\"phui-timeline-value\"\u003eMedium\u003c\/span\u003e priority.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6388077\" data-sigil=\"has-tooltip\" data-meta=\"0_103\"\u003e\u003cspan class=\"screen-only\"\u003eAug 17 2020, 8:34 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-17 08:34:31 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_108\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/bvjk4mger4kxiudavhib\/PHID-FILE-eakgrvfgjrcvkg647a7o\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/kostajh\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6389940\" id=\"6389940\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user-plus phui-timeline-icon\" data-meta=\"0_107\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/kostajh\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_30\"\u003ekostajh\u003c\/a\u003e subscribed.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6389940\" data-sigil=\"has-tooltip\" data-meta=\"0_106\"\u003e\u003cspan class=\"screen-only\"\u003eAug 17 2020, 4:42 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-17 16:42:10 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_111\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/ac3l7j336ju4mdgbssjt\/PHID-FILE-iewutaglmkyrs7tcmtr7\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/jijiki\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6391404\" id=\"6391404\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-columns phui-timeline-icon\" data-meta=\"0_110\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/jijiki\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_31\"\u003ejijiki\u003c\/a\u003e moved this task from \u003ca href=\"\/project\/board\/3775\/\" class=\"phui-handle\" data-sigil=\"hovercard\" data-meta=\"0_32\"\u003eIncoming \ud83d\udc2b\u003c\/a\u003e to \u003ca href=\"\/project\/board\/3775\/\" class=\"phui-handle handle-status-closed\" data-sigil=\"hovercard\" data-meta=\"0_33\"\u003e\ud83d\udd26Unused2\u003c\/a\u003e on the \u003ca href=\"\/tag\/serviceops\/\" class=\"phui-handle\" data-sigil=\"hovercard\" data-meta=\"0_34\"\u003eserviceops\u003c\/a\u003e board.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6391404\" data-sigil=\"has-tooltip\" data-meta=\"0_109\"\u003e\u003cspan class=\"screen-only\"\u003eAug 17 2020, 11:45 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-17 23:45:09 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell phui-timeline-yellow\" data-sigil=\"transaction anchor-container\" data-meta=\"0_115\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6392671\" id=\"6392671\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill fill-has-color phui-timeline-icon-fill-yellow\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-arrow-up phui-timeline-icon\" data-meta=\"0_113\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_35\"\u003etstarling\u003c\/a\u003e raised the priority of this task from \u003cspan class=\"phui-timeline-value\"\u003eMedium\u003c\/span\u003e to \u003cspan class=\"phui-timeline-value\"\u003eNeeds Triage\u003c\/span\u003e.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6392671\" data-sigil=\"has-tooltip\" data-meta=\"0_112\"\u003e\u003cspan class=\"screen-only\"\u003eAug 18 2020, 10:26 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-18 10:26:56 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-pencil phui-timeline-icon\" data-meta=\"0_114\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_36\"\u003etstarling\u003c\/a\u003e updated the task description. \u003ca href=\"\/transactions\/detail\/PHID-XACT-TASK-f3i4nkdhlwblg54\/\" data-sigil=\"workflow\"\u003e(Show Details)\u003c\/a\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell phui-timeline-green\" data-sigil=\"transaction anchor-container\" data-meta=\"0_124\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6392683\" id=\"6392683\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill fill-has-color phui-timeline-icon-fill-green\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user phui-timeline-icon\" data-meta=\"0_123\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_37\"\u003etstarling\u003c\/a\u003e claimed this task.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6392683\" data-sigil=\"has-tooltip\" data-meta=\"0_122\"\u003e\u003cspan class=\"screen-only\"\u003eAug 18 2020, 10:30 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-18 10:30:40 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_120\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_121\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_38\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cp\u003eAssigning to myself since implementation work is underway.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_127\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/ac3l7j336ju4mdgbssjt\/PHID-FILE-iewutaglmkyrs7tcmtr7\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/jijiki\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6392687\" id=\"6392687\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-columns phui-timeline-icon\" data-meta=\"0_126\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/jijiki\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_39\"\u003ejijiki\u003c\/a\u003e moved this task from \u003ca href=\"\/project\/board\/3775\/\" class=\"phui-handle handle-status-closed\" data-sigil=\"hovercard\" data-meta=\"0_40\"\u003e\ud83d\udd26Unused2\u003c\/a\u003e to \u003ca href=\"\/project\/board\/3775\/\" class=\"phui-handle\" data-sigil=\"hovercard\" data-meta=\"0_41\"\u003eIncoming \ud83d\udc2b\u003c\/a\u003e on the \u003ca href=\"\/tag\/serviceops\/\" class=\"phui-handle\" data-sigil=\"hovercard\" data-meta=\"0_42\"\u003eserviceops\u003c\/a\u003e board.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6392687\" data-sigil=\"has-tooltip\" data-meta=\"0_125\"\u003e\u003cspan class=\"screen-only\"\u003eAug 18 2020, 10:33 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-18 10:33:20 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_131\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/l2cg2zimvt2uq6xna6zg\/PHID-FILE-it2g7whiwxxkzdfzans5\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/Lucas_Werkmeister_WMDE\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6392691\" id=\"6392691\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-link phui-timeline-icon\" data-meta=\"0_129\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/Lucas_Werkmeister_WMDE\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_43\"\u003eLucas_Werkmeister_WMDE\u003c\/a\u003e mentioned this in \u003ca href=\"\/T240884\" class=\"phui-handle handle-status-closed\" data-sigil=\"hovercard\" data-meta=\"0_44\"\u003eT240884: RFC: How to evaluate user-provided regular expressions\u003c\/a\u003e.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6392691\" data-sigil=\"has-tooltip\" data-meta=\"0_128\"\u003e\u003cspan class=\"screen-only\"\u003eAug 18 2020, 10:34 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-18 10:34:41 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user-plus phui-timeline-icon\" data-meta=\"0_130\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/Lucas_Werkmeister_WMDE\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_45\"\u003eLucas_Werkmeister_WMDE\u003c\/a\u003e subscribed.\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_134\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/m25d4sm73mzvfxk7efxx\/PHID-FILE-zigk2s47ziyr7hqvpw7v\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/Ladsgroup\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6392695\" id=\"6392695\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user-plus phui-timeline-icon\" data-meta=\"0_133\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/Ladsgroup\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_46\"\u003eLadsgroup\u003c\/a\u003e subscribed.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6392695\" data-sigil=\"has-tooltip\" data-meta=\"0_132\"\u003e\u003cspan class=\"screen-only\"\u003eAug 18 2020, 10:36 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-18 10:36:49 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_137\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/5tdo3ybksmly7uox5w3w\/PHID-FILE-k6hgfcsgdizexxemgbkc\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/sbassett\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6393599\" id=\"6393599\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user-plus phui-timeline-icon\" data-meta=\"0_136\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/sbassett\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_47\"\u003esbassett\u003c\/a\u003e subscribed.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6393599\" data-sigil=\"has-tooltip\" data-meta=\"0_135\"\u003e\u003cspan class=\"screen-only\"\u003eAug 18 2020, 3:47 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-18 15:47:44 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell phui-timeline-green\" data-sigil=\"transaction anchor-container\" data-meta=\"0_142\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/3jdouglplnbkawzb5wdu\/PHID-FILE-knz7bp6gkvvl3ruasirw\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/AMooney\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6393794\" id=\"6393794\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill fill-has-color phui-timeline-icon-fill-green\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-arrow-right phui-timeline-icon\" data-meta=\"0_139\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/AMooney\/\" class=\"phui-handle handle-availability-disabled phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_48\"\u003e\u003cspan class=\"perfect-circle\"\u003e\u2022\u003c\/span\u003e AMooney\u003c\/a\u003e triaged this task as \u003cspan class=\"phui-timeline-value\"\u003eMedium\u003c\/span\u003e priority.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6393794\" data-sigil=\"has-tooltip\" data-meta=\"0_138\"\u003e\u003cspan class=\"screen-only\"\u003eAug 18 2020, 4:20 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-18 16:20:26 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-link phui-timeline-icon\" data-meta=\"0_140\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/AMooney\/\" class=\"phui-handle handle-availability-disabled phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_49\"\u003e\u003cspan class=\"perfect-circle\"\u003e\u2022\u003c\/span\u003e AMooney\u003c\/a\u003e edited projects, added \u003ca href=\"\/project\/view\/4149\/\" class=\"phui-handle handle-status-closed\" data-sigil=\"hovercard\" data-meta=\"0_50\"\u003ePlatform Team Workboards (Clinic Duty Team)\u003c\/a\u003e; removed \u003ca href=\"\/tag\/platform_engineering\/\" class=\"phui-handle handle-status-closed\" data-sigil=\"hovercard\" data-meta=\"0_51\"\u003ePlatform Engineering\u003c\/a\u003e.\u003c\/div\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-columns phui-timeline-icon\" data-meta=\"0_141\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/AMooney\/\" class=\"phui-handle handle-availability-disabled phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_52\"\u003e\u003cspan class=\"perfect-circle\"\u003e\u2022\u003c\/span\u003e AMooney\u003c\/a\u003e moved this task from \u003ca href=\"\/project\/board\/4149\/\" class=\"phui-handle\" data-sigil=\"hovercard\" data-meta=\"0_53\"\u003eInbox\u003c\/a\u003e to \u003ca href=\"\/project\/board\/4149\/\" class=\"phui-handle handle-status-closed\" data-sigil=\"hovercard\" data-meta=\"0_54\"\u003eDoing(WIP:5)\u003c\/a\u003e on the \u003ca href=\"\/project\/view\/4149\/\" class=\"phui-handle handle-status-closed\" data-sigil=\"hovercard\" data-meta=\"0_55\"\u003ePlatform Team Workboards (Clinic Duty Team)\u003c\/a\u003e board.\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_145\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6395250\" id=\"6395250\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-pencil phui-timeline-icon\" data-meta=\"0_144\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_56\"\u003etstarling\u003c\/a\u003e updated the task description. \u003ca href=\"\/transactions\/detail\/PHID-XACT-TASK-57r6qnnxd3rlyj4\/\" data-sigil=\"workflow\"\u003e(Show Details)\u003c\/a\u003e\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6395250\" data-sigil=\"has-tooltip\" data-meta=\"0_143\"\u003e\u003cspan class=\"screen-only\"\u003eAug 19 2020, 12:37 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-19 00:37:41 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_148\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/gjkyraeh6ascv7vkj3ke\/PHID-FILE-czquixv3lk45jved74s2\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/CDanis\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6395251\" id=\"6395251\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user-plus phui-timeline-icon\" data-meta=\"0_147\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/CDanis\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_57\"\u003eCDanis\u003c\/a\u003e subscribed.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6395251\" data-sigil=\"has-tooltip\" data-meta=\"0_146\"\u003e\u003cspan class=\"screen-only\"\u003eAug 19 2020, 12:42 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-19 00:42:05 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_161\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/bvjk4mger4kxiudavhib\/PHID-FILE-eakgrvfgjrcvkg647a7o\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/kostajh\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-badges\"\u003e\u003cul class=\"phui-badge-flex-view grouped flex-view-collapsed \"\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-blue \" href=\"\/badges\/view\/22\/\" data-sigil=\"has-tooltip\" data-meta=\"0_157\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-graduation-cap\" data-meta=\"0_158\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-blue \" href=\"\/badges\/view\/18\/\" data-sigil=\"has-tooltip\" data-meta=\"0_159\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-star\" data-meta=\"0_160\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6396222\" id=\"6396222\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_156\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/kostajh\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_58\"\u003ekostajh\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6396222\" data-sigil=\"has-tooltip\" data-meta=\"0_155\"\u003e\u003cspan class=\"screen-only\"\u003eAug 19 2020, 12:34 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-19 12:34:55 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_153\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_154\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_59\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cp\u003eThis might substantially complicate the implementation, but it would be nice if you could do something like:\u003c\/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\" data-sigil=\"remarkup-code-block\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"nv\"\u003e$result\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"nc\" data-symbol-name=\"MediaWikiServices\"\u003eMediaWikiServices\u003c\/span\u003e\u003cspan class=\"o\"\u003e::\u003c\/span\u003e\u003cspan class=\"nf\" data-symbol-context=\"MediaWikiServices\" data-symbol-name=\"getInstance\"\u003egetInstance\u003c\/span\u003e\u003cspan class=\"o\"\u003e()\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"getCommandFactory\"\u003egetCommandFactory\u003c\/span\u003e\u003cspan class=\"o\"\u003e()\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"getBoxedCommand\"\u003egetBoxedCommand\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"o\"\u003e...\u003c\/span\u003e \u003cspan class=\"no\"\u003eparams\u003c\/span\u003e \u003cspan class=\"o\"\u003e...\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"setTimeLimit\"\u003esetTimeLimit\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"mi\"\u003e2000\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"execute\"\u003eexecute\u003c\/span\u003e\u003cspan class=\"o\"\u003e();\u003c\/span\u003e\u003c\/pre\u003e\u003c\/div\u003e\n\n\u003cp\u003eThen, if the command execution exceeds the value set with \u003ctt class=\"remarkup-monospaced\"\u003esetTimeLimit()\u003c\/tt\u003e, the command execution is halted and \u003ctt class=\"remarkup-monospaced\"\u003e$result\u003c\/tt\u003e is set to an error code so the caller knows the result is due to the time limit being exceeded.\u003c\/p\u003e\n\n\u003cp\u003eFor context, \u003ca href=\"\/T258978\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_2\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT258978\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e and \u003ca href=\"https:\/\/docs.google.com\/document\/d\/1Y0Jt2N20e7-H83MMAqVYcSB-UIGba1YoSQE39z2dlds\/edit#heading=h.3ud9m9oajb9i\" class=\"remarkup-link\" target=\"_blank\" rel=\"noreferrer\"\u003ethis document\u003c\/a\u003e outline a process where the GrowthExperiments extension would us the \u003ctt class=\"remarkup-monospaced\"\u003eSearchDataForIndex\u003c\/tt\u003e hook to fetch data from an external service to populate additional metadata for an article. The problem is that we don't know in advance how long this external service might take, other than knowing it could vary based on article length, and it would be nice to be able to enforce an upper limit on its execution time so as to not cause problems for the job which executes that hook.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_170\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6396259\" id=\"6396259\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_169\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_60\"\u003etstarling\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6396259\" data-sigil=\"has-tooltip\" data-meta=\"0_168\"\u003e\u003cspan class=\"screen-only\"\u003eAug 19 2020, 12:57 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-19 12:57:42 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_166\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_167\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_61\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cblockquote class=\"remarkup-reply-block\"\u003e\n\u003cdiv class=\"remarkup-reply-head\"\u003eIn \u003ca href=\"\/T260330#6396222\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_3\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT260330#6396222\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e, \u003ca href=\"\/p\/kostajh\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_4\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@kostajh\u003c\/span\u003e\u003c\/a\u003e wrote:\u003c\/div\u003e\n\u003cdiv class=\"remarkup-reply-body\"\u003e\u003cp\u003eThen, if the command execution exceeds the value set with \u003ctt class=\"remarkup-monospaced\"\u003esetTimeLimit()\u003c\/tt\u003e, the command execution is halted and \u003ctt class=\"remarkup-monospaced\"\u003e$result\u003c\/tt\u003e is set to an error code so the caller knows the result is due to the time limit being exceeded.\u003c\/p\u003e\u003c\/div\u003e\n\u003c\/blockquote\u003e\n\n\u003cp\u003eThis already exists, and will continue to exist in the new system. You can use Shell::command()->limits(['walltime' => 2000]) in the existing system. Or use the fourth parameter to wfShellExec(). Shell commands have a default limit of $wgMaxShellWallTime=180 seconds, and a CPU time limit of $wgMaxShellTime=50 seconds.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_183\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/bvjk4mger4kxiudavhib\/PHID-FILE-eakgrvfgjrcvkg647a7o\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/kostajh\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-badges\"\u003e\u003cul class=\"phui-badge-flex-view grouped flex-view-collapsed \"\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-blue \" href=\"\/badges\/view\/22\/\" data-sigil=\"has-tooltip\" data-meta=\"0_179\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-graduation-cap\" data-meta=\"0_180\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-blue \" href=\"\/badges\/view\/18\/\" data-sigil=\"has-tooltip\" data-meta=\"0_181\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-star\" data-meta=\"0_182\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6396291\" id=\"6396291\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_178\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/kostajh\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_62\"\u003ekostajh\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6396291\" data-sigil=\"has-tooltip\" data-meta=\"0_177\"\u003e\u003cspan class=\"screen-only\"\u003eAug 19 2020, 1:11 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-19 13:11:34 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_175\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_176\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_63\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cblockquote class=\"remarkup-reply-block\"\u003e\n\u003cdiv class=\"remarkup-reply-head\"\u003eIn \u003ca href=\"\/T260330#6396259\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_5\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT260330#6396259\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e, \u003ca href=\"\/p\/tstarling\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_6\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@tstarling\u003c\/span\u003e\u003c\/a\u003e wrote:\u003c\/div\u003e\n\u003cdiv class=\"remarkup-reply-body\"\u003e\u003cp\u003eThis already exists, and will continue to exist in the new system. You can use Shell::command()->limits(['walltime' => 2000]) in the existing system. Or use the fourth parameter to wfShellExec(). Shell commands have a default limit of $wgMaxShellWallTime=180 seconds, and a CPU time limit of $wgMaxShellTime=50 seconds.\u003c\/p\u003e\u003c\/div\u003e\n\u003c\/blockquote\u003e\n\n\u003cp\u003eAh, great. Thanks.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_187\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/mcdy6bokf2bfd6lhrj5x\/PHID-FILE-hvay22mxxy4ab7u76frl\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/Addshore\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6396703\" id=\"6396703\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-trophy phui-timeline-icon\" data-meta=\"0_185\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view sprite-tokens tokens-like-1 phui-timeline-token\" data-meta=\"0_186\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003ca href=\"\/p\/Addshore\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_64\"\u003eAddshore\u003c\/a\u003e awarded a token.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6396703\" data-sigil=\"has-tooltip\" data-meta=\"0_184\"\u003e\u003cspan class=\"screen-only\"\u003eAug 19 2020, 3:05 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-19 15:05:11 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_200\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/m25d4sm73mzvfxk7efxx\/PHID-FILE-zigk2s47ziyr7hqvpw7v\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/Ladsgroup\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-badges\"\u003e\u003cul class=\"phui-badge-flex-view grouped flex-view-collapsed \"\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-orange \" href=\"\/badges\/view\/17\/\" data-sigil=\"has-tooltip\" data-meta=\"0_196\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-rocket\" data-meta=\"0_197\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-indigo \" href=\"\/badges\/view\/15\/\" data-sigil=\"has-tooltip\" data-meta=\"0_198\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-eye\" data-meta=\"0_199\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6398816\" id=\"6398816\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_195\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/Ladsgroup\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_65\"\u003eLadsgroup\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6398816\" data-sigil=\"has-tooltip\" data-meta=\"0_194\"\u003e\u003cspan class=\"screen-only\"\u003eAug 20 2020, 6:46 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-20 06:46:39 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_192\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_193\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_66\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cp\u003eMy 2c, I would really appreciate. having some sort of support for usecases like \u003ca href=\"\/T240884\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_7\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT240884: RFC: How to evaluate user-provided regular expressions\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e while we are building something like this now. If not possible, we can just fall back to what Lucas suggested in \u003ca href=\"\/T240884#6396660\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_8\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT240884#6396660\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_209\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6398851\" id=\"6398851\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_208\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_67\"\u003etstarling\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6398851\" data-sigil=\"has-tooltip\" data-meta=\"0_207\"\u003e\u003cspan class=\"screen-only\"\u003eAug 20 2020, 7:06 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-20 07:06:51 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_205\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_206\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_68\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cp\u003eFrom what I understand, the service will run inside the sandbox, and eval() can be done in this service with relative safety. I planned on having eval() in there for another reason: I'm considering allowing callers to subclass BoxedCommand. However \u003ca href=\"\/p\/Joe\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_9\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@Joe\u003c\/span\u003e\u003c\/a\u003e was not a fan of this idea. We won't be providing a full MediaWiki install inside the sandbox, with autoloading, so there is a risk of development and production instances working differently if the default in development will be local in-process execution.\u003c\/p\u003e\n\n\u003cp\u003eMy plan for subclassing was to allow the caller to specify a class name. Then the class file would be identified with ReflectionClass::getFileName(), and transferred to the service like other input files, where it can be run with require(). The executed code would have access to a plain PHP environment, and the Shellbox library, but not much else.\u003c\/p\u003e\n\n\u003cp\u003eIt would be possible to offer a more general facility for running PHP code along these lines, although it changes how we think about this project and its interfaces.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_220\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/4vfodng5xaao26r6l2bf\/PHID-FILE-2gvu7et6e6bs2cswr2hw\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/Joe\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-badges\"\u003e\u003cul class=\"phui-badge-flex-view grouped flex-view-collapsed \"\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-orange \" href=\"\/badges\/view\/17\/\" data-sigil=\"has-tooltip\" data-meta=\"0_218\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-rocket\" data-meta=\"0_219\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6399137\" id=\"6399137\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_217\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/Joe\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_69\"\u003eJoe\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6399137\" data-sigil=\"has-tooltip\" data-meta=\"0_216\"\u003e\u003cspan class=\"screen-only\"\u003eAug 20 2020, 8:53 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-20 08:53:45 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_214\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_215\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_70\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cp\u003eHi, sorry for not adding some comments earlier, I was busy with the aftermath of an UBN! task.\u003c\/p\u003e\n\n\u003cp\u003eLet me list some of the characteristics of this service, that I'd expect.\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eSecurity\u003c\/strong\u003e\u003c\/p\u003e\n\n\u003cp\u003eExternal protection\/isolation execution will be provided by kubernetes and linux. While we might consider using gvisor to further limit what can be executed within a container, it's not part of this first iteration.\u003c\/p\u003e\n\n\u003cul class=\"remarkup-list\"\u003e\n\u003cli class=\"remarkup-list-item\"\u003eThe service will be executed as user nobody\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003eThe service will be firewalled from all network access. We might consider adding specific exceptions, but in general I'm against it\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003eWe will have a base docker container with the php code and php-fpm, upon which we will create the individual containers, one per external executable. This is a good way to reduce the attack surface.\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003eLimits on execution (in terms of memory and cpu time) for each external program will be determined in configuration and enforced by kubernetes\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003eThe user the service runs as should have no write rights on the container filesystem, besides a specific throwaway directory (mounted with noexec?)\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eSo when the service is running in production, we want it to just set time limits for its shellouts, any attempt to work with cgroups or seccomp would fail - that needs to be done externally.\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eRouting\u003c\/strong\u003e\u003c\/p\u003e\n\n\u003cp\u003eAs mentioned above, we'd like to have separate containers for the various shellouts. This means each service will only need to respond to requests for a specific shellout. The php microservice should thus be configurable to wire its routing as follows:\u003c\/p\u003e\n\n\u003cul class=\"remarkup-list\"\u003e\n\u003cli class=\"remarkup-list-item\"\u003e\u003ctt class=\"remarkup-monospaced\"\u003e\/healthz\u003c\/tt\u003e a probe to know if the service is available\/ready\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003e\u003ctt class=\"remarkup-monospaced\"\u003e\/\u003c\/tt\u003e some form of application manifest? An OpenAPI spec?\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003e\u003ctt class=\"remarkup-monospaced\"\u003e\/exec\u003c\/tt\u003e (or a less terrible name) the endpoint for executing the shellout.\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eRequests will be routed to the correct microservice by a router application that will be able to direct requests for, say, \u003ctt class=\"remarkup-monospaced\"\u003e\/syntaxhighlight\u003c\/tt\u003e to the correct container's \u003ctt class=\"remarkup-monospaced\"\u003e\/exec\u003c\/tt\u003e endpoint. A separate task about this implementation will be opened soon.\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eConfiguration\u003c\/strong\u003e\u003c\/p\u003e\n\n\u003cp\u003eI would love for the microservice to be configurable in terms of: which executable to launch within \u003ctt class=\"remarkup-monospaced\"\u003e\/exec\u003c\/tt\u003e, and what parameters, or parameters mask, to accept, what timeout to establish.\u003c\/p\u003e\n\n\u003cp\u003eSuch configuration should preferably not be specified as php code, but in a docker-friendly way - so possibly as environment variables.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_223\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/pftw7tn2jgpwaqdmxbtd\/PHID-FILE-4peudqvgp45hlsggbblo\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/TK-999\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6400041\" id=\"6400041\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user-plus phui-timeline-icon\" data-meta=\"0_222\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/TK-999\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_71\"\u003eTK-999\u003c\/a\u003e subscribed.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6400041\" data-sigil=\"has-tooltip\" data-meta=\"0_221\"\u003e\u003cspan class=\"screen-only\"\u003eAug 20 2020, 2:37 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-20 14:37:26 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_232\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6401694\" id=\"6401694\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_231\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_72\"\u003etstarling\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6401694\" data-sigil=\"has-tooltip\" data-meta=\"0_230\"\u003e\u003cspan class=\"screen-only\"\u003eAug 21 2020, 2:18 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-21 02:18:32 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_228\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_229\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_73\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cblockquote class=\"remarkup-reply-block\"\u003e\n\u003cdiv class=\"remarkup-reply-head\"\u003eIn \u003ca href=\"\/T260330#6399137\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_10\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT260330#6399137\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e, \u003ca href=\"\/p\/Joe\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_11\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@Joe\u003c\/span\u003e\u003c\/a\u003e wrote:\u003c\/div\u003e\n\u003cdiv class=\"remarkup-reply-body\"\u003e\u003cul class=\"remarkup-list\"\u003e\n\u003cli class=\"remarkup-list-item\"\u003eThe service will be executed as user nobody\u003c\/li\u003e\n\u003c\/ul\u003e\u003c\/div\u003e\n\u003c\/blockquote\u003e\n\n\u003cp\u003eI would suggest using a new system user rather than nobody. The problem with nobody is that as soon as two different things on a system use it, they can attack each other. Any file owned by nobody can be written to by any service running as nobody.\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cul class=\"remarkup-list\"\u003e\n\u003cli class=\"remarkup-list-item\"\u003eThe service will be firewalled from all network access. We might consider adding specific exceptions, but in general I'm against it\u003c\/li\u003e\n\u003c\/ul\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003ePresumably you have to at least allow inbound HTTP connections. That's a slight regression in attack surface compared to firejail, since under firejail, commands have a network namespace with only localhost, whereas this container will presumably at least need a host link.\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cul class=\"remarkup-list\"\u003e\n\u003cli class=\"remarkup-list-item\"\u003eLimits on execution (in terms of memory and cpu time) for each external program will be determined in configuration and enforced by kubernetes\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eSo when the service is running in production, we want it to just set time limits for its shellouts, any attempt to work with cgroups or seccomp would fail - that needs to be done externally.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eThe interface I'm proposing allows the caller to specify time and memory limits. Memory limits set this way will presumably be ignored. But maybe the service could do its own setrlimit() to respect the time limits set by the caller, in addition to a (slightly higher) limit on the container. It would be nice to be able to give backwards compatible error messages when a timeout is reached. Presumably, if the container is killed, we will just see a generic HTTP 500 error.\u003c\/p\u003e\n\n\u003cp\u003eDo we need any log messages from inside the container? For example, if the service gets an error while deleting a temporary file, should it tell us about that? My plan for log messages was to buffer them and return them to the caller, but that means that if the container is killed, we lose the messages.\u003c\/p\u003e\n\n\u003cp\u003eWill there be a new container created for each command? Or will containers be persistent and service multiple commands?\u003c\/p\u003e\n\n\u003cp\u003eIf there will be a per-command container, then we have to think about startup time. For example, I read at \u003ca href=\"https:\/\/gvisor.dev\/docs\/architecture_guide\/performance\/\" class=\"remarkup-link\" target=\"_blank\" rel=\"noreferrer\"\u003ehttps:\/\/gvisor.dev\/docs\/architecture_guide\/performance\/\u003c\/a\u003e that gvisor has a startup time on the order of 1s. The latency can be hidden by starting containers in advance, but it still impacts the throughput.\u003c\/p\u003e\n\n\u003cp\u003ephp-fpm has a startup time of about 80ms when I measure it locally. Parse time for service startup should be less than that, especially if we avoid large dependencies like REST frameworks.\u003c\/p\u003e\n\n\u003cp\u003eIf containers are persistent and serve multiple requests, then we should consider whether a malicious command could become persistent within the container, attacking subsequent commands. That's not possible with firejail because it shuts down the per-command container with kill(-1, SIGKILL).\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cp\u003eAs mentioned above, we'd like to have separate containers for the various shellouts. This means each service will only need to respond to requests for a specific shellout. The php microservice should thus be configurable to wire its routing as follows:\u003c\/p\u003e\n\n\u003cul class=\"remarkup-list\"\u003e\n\u003cli class=\"remarkup-list-item\"\u003e\u003ctt class=\"remarkup-monospaced\"\u003e\/healthz\u003c\/tt\u003e a probe to know if the service is available\/ready\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003e\u003ctt class=\"remarkup-monospaced\"\u003e\/\u003c\/tt\u003e some form of application manifest? An OpenAPI spec?\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003e\u003ctt class=\"remarkup-monospaced\"\u003e\/exec\u003c\/tt\u003e (or a less terrible name) the endpoint for executing the shellout.\u003c\/li\u003e\n\u003c\/ul\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eThis is an RPC service, not a REST service. Parameters can be in query strings. REST is a lot of hassle in PHP, so I don't really want to do it if there's no need for that apart from a desire to be fashionable.\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cp\u003eI would love for the microservice to be configurable in terms of: which executable to launch within \u003ctt class=\"remarkup-monospaced\"\u003e\/exec\u003c\/tt\u003e, and what parameters, or parameters mask, to accept, what timeout to establish.\u003c\/p\u003e\n\n\u003cp\u003eSuch configuration should preferably not be specified as php code, but in a docker-friendly way - so possibly as environment variables.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eWe could have configuration that validates the parameters specified by the caller. Configuration actually in an environment variable sounds a bit weird. Maybe an environment variable could specify the path to a JSON file. So you could have a collection of JSON profiles bind-mounted into the container, and select which one you want using an environment variable.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_235\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-minor-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003ca name=\"6401748\" id=\"6401748\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-pencil phui-timeline-icon\" data-meta=\"0_234\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_74\"\u003etstarling\u003c\/a\u003e updated the task description. \u003ca href=\"\/transactions\/detail\/PHID-XACT-TASK-elqbrhr3jsf2wax\/\" data-sigil=\"workflow\"\u003e(Show Details)\u003c\/a\u003e\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6401748\" data-sigil=\"has-tooltip\" data-meta=\"0_233\"\u003e\u003cspan class=\"screen-only\"\u003eAug 21 2020, 6:21 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-21 06:21:34 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_244\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6401750\" id=\"6401750\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_243\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_75\"\u003etstarling\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6401750\" data-sigil=\"has-tooltip\" data-meta=\"0_242\"\u003e\u003cspan class=\"screen-only\"\u003eAug 21 2020, 6:36 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-21 06:36:37 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_240\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_241\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_76\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cp\u003eI'm reconsidering the layout abstraction I had planned, with inputs\/ and outputs\/ subdirectories under the working directory. It's simpler to allow slashes in filenames and to allow files to go anywhere under the working directory. So you could have\u003c\/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\" data-sigil=\"remarkup-code-block\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"nv\"\u003e$result\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$commandFactory\u003c\/span\u003e\u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"newBoxedCommand\"\u003enewBoxedCommand\u003c\/span\u003e\u003cspan class=\"o\"\u003e()\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"params\"\u003eparams\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'convert'\u003c\/span\u003e\u003cspan class=\"o\"\u003e,\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'input.svg'\u003c\/span\u003e\u003cspan class=\"o\"\u003e,\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'output.png'\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"addInputFileFromString\"\u003eaddInputFileFromString\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'input.svg'\u003c\/span\u003e\u003cspan class=\"o\"\u003e,\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$svgContents\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"addOutputFileToString\"\u003eaddOutputFileToString\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'output.png'\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"execute\"\u003eexecute\u003c\/span\u003e\u003cspan class=\"o\"\u003e();\u003c\/span\u003e\n\n\u003cspan class=\"nv\"\u003e$pngContents\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$result\u003c\/span\u003e\u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"getFileContents\"\u003egetFileContents\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'output.png'\u003c\/span\u003e \u003cspan class=\"o\"\u003e);\u003c\/span\u003e\u003c\/pre\u003e\u003c\/div\u003e\n\n\u003cp\u003eThis is with string literal filenames as originally proposed, before Daniel's objections led to my last couple of task description edits. But string literals are not so bad if they are all filenames in the same namespace. If you don't like the repeated literals, you can just do\u003c\/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\" data-sigil=\"remarkup-code-block\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"nv\"\u003e$input\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'input.svg'\u003c\/span\u003e\u003cspan class=\"o\"\u003e;\u003c\/span\u003e\n\u003cspan class=\"nv\"\u003e$output\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'output.svg'\u003c\/span\u003e\u003cspan class=\"o\"\u003e;\u003c\/span\u003e\n\n\u003cspan class=\"nv\"\u003e$result\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$commandFactory\u003c\/span\u003e\u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"newBoxedCommand\"\u003enewBoxedCommand\u003c\/span\u003e\u003cspan class=\"o\"\u003e()\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"params\"\u003eparams\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'convert'\u003c\/span\u003e\u003cspan class=\"o\"\u003e,\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$input\u003c\/span\u003e\u003cspan class=\"o\"\u003e,\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$output\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"addInputFileFromString\"\u003eaddInputFileFromString\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$input\u003c\/span\u003e\u003cspan class=\"o\"\u003e,\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$svgContents\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"addOutputFileToString\"\u003eaddOutputFileToString\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$output\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"execute\"\u003eexecute\u003c\/span\u003e\u003cspan class=\"o\"\u003e();\u003c\/span\u003e\n\n\u003cspan class=\"nv\"\u003e$pngContents\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$result\u003c\/span\u003e\u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"getFileContents\"\u003egetFileContents\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$output\u003c\/span\u003e \u003cspan class=\"o\"\u003e);\u003c\/span\u003e\u003c\/pre\u003e\u003c\/div\u003e\n\n\u003cp\u003eI don't know if we really gain much from object encapsulation of files, and it tends to break the fluent style and it makes it more difficult to figure out what the shell command will be.\u003c\/p\u003e\n\n\u003cp\u003eOne reason for avoiding inputs\/ and outputs\/ is that LilyPond, which is supposed to be the initial use case, puts output files into the current directory by default. It's easier to port it if we can just deal with that convention.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_255\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/v5wmnfiaelrd6nztxd3a\/PHID-FILE-s57znldbv3qchtewuryd\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/daniel\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-badges\"\u003e\u003cul class=\"phui-badge-flex-view grouped flex-view-collapsed \"\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-indigo \" href=\"\/badges\/view\/14\/\" data-sigil=\"has-tooltip\" data-meta=\"0_253\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-empire\" data-meta=\"0_254\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6405293\" id=\"6405293\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-user-plus phui-timeline-icon\" data-meta=\"0_252\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/daniel\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_78\"\u003edaniel\u003c\/a\u003e subscribed.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6405293\" data-sigil=\"has-tooltip\" data-meta=\"0_251\"\u003e\u003cspan class=\"screen-only\"\u003eAug 24 2020, 8:30 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-24 08:30:06 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_249\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_250\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_77\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cblockquote class=\"remarkup-reply-block\"\u003e\n\u003cdiv class=\"remarkup-reply-head\"\u003eIn \u003ca href=\"\/T260330#6401750\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_12\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT260330#6401750\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e, \u003ca href=\"\/p\/tstarling\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_13\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@tstarling\u003c\/span\u003e\u003c\/a\u003e wrote:\u003c\/div\u003e\n\u003cdiv class=\"remarkup-reply-body\"\u003e\u003cp\u003eI don't know if we really gain much from object encapsulation of files, and it tends to break the fluent style and it makes it more difficult to figure out what the shell command will be.\u003c\/p\u003e\u003c\/div\u003e\n\u003c\/blockquote\u003e\n\n\u003cp\u003eI guess you are right. My proposal to model input and output files as objects was really just meant as an idea to explore, not an objection to your design.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_267\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/v5wmnfiaelrd6nztxd3a\/PHID-FILE-s57znldbv3qchtewuryd\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/daniel\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-badges\"\u003e\u003cul class=\"phui-badge-flex-view grouped flex-view-collapsed \"\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-indigo \" href=\"\/badges\/view\/14\/\" data-sigil=\"has-tooltip\" data-meta=\"0_265\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-empire\" data-meta=\"0_266\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6405301\" id=\"6405301\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_264\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/daniel\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_79\"\u003edaniel\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003eEdited\u003cspan class=\"visual-only\" aria-hidden=\"true\"\u003e \u00b7 \u003c\/span\u003e\u003ca href=\"#6405301\" data-sigil=\"has-tooltip\" data-meta=\"0_263\"\u003e\u003cspan class=\"screen-only\"\u003eAug 24 2020, 8:32 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-24 08:32:13 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_261\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_262\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_80\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cblockquote class=\"remarkup-reply-block\"\u003e\n\u003cdiv class=\"remarkup-reply-head\"\u003eIn \u003ca href=\"\/T240884#6401731\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_14\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT240884#6401731\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e, \u003ca href=\"\/p\/tstarling\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_15\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@tstarling\u003c\/span\u003e\u003c\/a\u003e wrote:\u003c\/div\u003e\n\u003cdiv class=\"remarkup-reply-body\"\u003e\u003cp\u003eOK, I'm adding PHP execution to the service.\u003c\/p\u003e\u003c\/div\u003e\n\u003c\/blockquote\u003e\n\n\u003cp\u003eAm I correct to assume that the PHP execution mode will just be a shorthand for something like \u003ctt class=\"remarkup-monospaced\"\u003ephp -r 'echo "Hello";'\u003c\/tt\u003e?\u003c\/p\u003e\n\n\u003cp\u003ePerhaps like this?\u003c\/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\" data-sigil=\"remarkup-code-block\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"nv\"\u003e$result\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$commandFactory\u003c\/span\u003e\u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"newBoxedCommand\"\u003enewBoxedCommand\u003c\/span\u003e\u003cspan class=\"o\"\u003e()\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"php\"\u003ephp\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'echo "Hello";'\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"execute\"\u003eexecute\u003c\/span\u003e\u003cspan class=\"o\"\u003e();\u003c\/span\u003e\u003c\/pre\u003e\u003c\/div\u003e\n\n\u003cp\u003eOr did you think of doing something along the lines of\u003c\/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\" data-sigil=\"remarkup-code-block\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"nv\"\u003e$result\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$commandFactory\u003c\/span\u003e\u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"newBoxedCommand\"\u003enewBoxedCommand\u003c\/span\u003e\u003cspan class=\"o\"\u003e()\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"setPhpFile\"\u003esetPhpFile\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"kc\"\u003e__DIR__\u003c\/span\u003e \u003cspan class=\"o\"\u003e.\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'\/Hello.php'\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"params\"\u003eparams\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'--hello World'\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"execute\"\u003eexecute\u003c\/span\u003e\u003cspan class=\"o\"\u003e();\u003c\/span\u003e\u003c\/pre\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_278\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/4vfodng5xaao26r6l2bf\/PHID-FILE-2gvu7et6e6bs2cswr2hw\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/Joe\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-badges\"\u003e\u003cul class=\"phui-badge-flex-view grouped flex-view-collapsed \"\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-orange \" href=\"\/badges\/view\/17\/\" data-sigil=\"has-tooltip\" data-meta=\"0_276\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-rocket\" data-meta=\"0_277\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6405691\" id=\"6405691\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_275\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/Joe\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_81\"\u003eJoe\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6405691\" data-sigil=\"has-tooltip\" data-meta=\"0_274\"\u003e\u003cspan class=\"screen-only\"\u003eAug 24 2020, 11:15 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-24 11:15:51 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_272\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_273\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_82\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cblockquote class=\"remarkup-reply-block\"\u003e\n\u003cdiv class=\"remarkup-reply-head\"\u003eIn \u003ca href=\"\/T260330#6401694\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_16\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT260330#6401694\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e, \u003ca href=\"\/p\/tstarling\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_17\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@tstarling\u003c\/span\u003e\u003c\/a\u003e wrote:\u003c\/div\u003e\n\u003cdiv class=\"remarkup-reply-body\"\u003e\u003c\/div\u003e\n\u003c\/blockquote\u003e\n\n\n\n\u003cblockquote\u003e\u003cblockquote\u003e\u003cul class=\"remarkup-list\"\u003e\n\u003cli class=\"remarkup-list-item\"\u003eThe service will be firewalled from all network access. We might consider adding specific exceptions, but in general I'm against it\u003c\/li\u003e\n\u003c\/ul\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003ePresumably you have to at least allow inbound HTTP connections. That's a slight regression in attack surface compared to firejail, since under firejail, commands have a network namespace with only localhost, whereas this container will presumably at least need a host link.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eYes, I meant we will disallow any outbound network request, and only open inbound HTTP connections from the gateway, that will also be running in kubernetes.\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cblockquote\u003e\u003cul class=\"remarkup-list\"\u003e\n\u003cli class=\"remarkup-list-item\"\u003eLimits on execution (in terms of memory and cpu time) for each external program will be determined in configuration and enforced by kubernetes\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eSo when the service is running in production, we want it to just set time limits for its shellouts, any attempt to work with cgroups or seccomp would fail - that needs to be done externally.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eThe interface I'm proposing allows the caller to specify time and memory limits. Memory limits set this way will presumably be ignored. But maybe the service could do its own setrlimit() to respect the time limits set by the caller, in addition to a (slightly higher) limit on the container. It would be nice to be able to give backwards compatible error messages when a timeout is reached. Presumably, if the container is killed, we will just see a generic HTTP 500 error.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eTime limits will still be managed by the application, probably with an upper bound set by the gateway.\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cp\u003eDo we need any log messages from inside the container? For example, if the service gets an error while deleting a temporary file, should it tell us about that? My plan for log messages was to buffer them and return them to the caller, but that means that if the container is killed, we lose the messages.\u003c\/p\u003e\n\n\u003cp\u003eWill there be a new container created for each command? Or will containers be persistent and service multiple commands?\u003c\/p\u003e\n\n\u003cp\u003eIf there will be a per-command container, then we have to think about startup time. For example, I read at \u003ca href=\"https:\/\/gvisor.dev\/docs\/architecture_guide\/performance\/\" class=\"remarkup-link\" target=\"_blank\" rel=\"noreferrer\"\u003ehttps:\/\/gvisor.dev\/docs\/architecture_guide\/performance\/\u003c\/a\u003e that gvisor has a startup time on the order of 1s. The latency can be hidden by starting containers in advance, but it still impacts the throughput.\u003c\/p\u003e\n\n\u003cp\u003ephp-fpm has a startup time of about 80ms when I measure it locally. Parse time for service startup should be less than that, especially if we avoid large dependencies like REST frameworks.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eMy current idea is that we will run these "nanoservices" as normal kubernetes services, so the containers will run until they get killed for an external reason, and be restarted if that happens. The reason for this is exactly that the startup time is too large (you also have to add the work of the kubernetes scheduler). The issue with that is of course that\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cp\u003eIf containers are persistent and serve multiple requests, then we should consider whether a malicious command could become persistent within the container, attacking subsequent commands. That's not possible with firejail because it shuts down the per-command container with kill(-1, SIGKILL).\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eThis holds true. I'm still unsure how to balance it besides "the container is an empty shell anyways, which will hold no credentials nor any sensible data".\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cblockquote\u003e\u003cp\u003eAs mentioned above, we'd like to have separate containers for the various shellouts. This means each service will only need to respond to requests for a specific shellout. The php microservice should thus be configurable to wire its routing as follows:\u003c\/p\u003e\n\n\u003cul class=\"remarkup-list\"\u003e\n\u003cli class=\"remarkup-list-item\"\u003e\u003ctt class=\"remarkup-monospaced\"\u003e\/healthz\u003c\/tt\u003e a probe to know if the service is available\/ready\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003e\u003ctt class=\"remarkup-monospaced\"\u003e\/\u003c\/tt\u003e some form of application manifest? An OpenAPI spec?\u003c\/li\u003e\n\u003cli class=\"remarkup-list-item\"\u003e\u003ctt class=\"remarkup-monospaced\"\u003e\/exec\u003c\/tt\u003e (or a less terrible name) the endpoint for executing the shellout.\u003c\/li\u003e\n\u003c\/ul\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eThis is an RPC service, not a REST service. Parameters can be in query strings. REST is a lot of hassle in PHP, so I don't really want to do it if there's no need for that apart from a desire to be fashionable.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eThat's just how our services are organized in production right now. The only think I'd like to hold is keeping the health check url at \u003ctt class=\"remarkup-monospaced\"\u003e\/healthz\u003c\/tt\u003e as that's a de-facto standard.\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cblockquote\u003e\u003cp\u003eI would love for the microservice to be configurable in terms of: which executable to launch within \u003ctt class=\"remarkup-monospaced\"\u003e\/exec\u003c\/tt\u003e, and what parameters, or parameters mask, to accept, what timeout to establish.\u003c\/p\u003e\n\n\u003cp\u003eSuch configuration should preferably not be specified as php code, but in a docker-friendly way - so possibly as environment variables.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eWe could have configuration that validates the parameters specified by the caller. Configuration actually in an environment variable sounds a bit weird. Maybe an environment variable could specify the path to a JSON file. So you could have a collection of JSON profiles bind-mounted into the container, and select which one you want using an environment variable.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003ethat is what I was thinking of, yes.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_287\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6405702\" id=\"6405702\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_286\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_83\"\u003etstarling\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6405702\" data-sigil=\"has-tooltip\" data-meta=\"0_285\"\u003e\u003cspan class=\"screen-only\"\u003eAug 24 2020, 11:21 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-24 11:21:36 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_283\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_284\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_84\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cblockquote class=\"remarkup-reply-block\"\u003e\n\u003cdiv class=\"remarkup-reply-head\"\u003eIn \u003ca href=\"\/T260330#6405301\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_19\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT260330#6405301\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e, \u003ca href=\"\/p\/daniel\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_21\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@daniel\u003c\/span\u003e\u003c\/a\u003e wrote:\u003c\/div\u003e\n\u003cdiv class=\"remarkup-reply-body\"\u003e\u003cblockquote class=\"remarkup-reply-block\"\u003e\n\u003cdiv class=\"remarkup-reply-head\"\u003eIn \u003ca href=\"\/T240884#6401731\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_18\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT240884#6401731\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e, \u003ca href=\"\/p\/tstarling\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_20\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@tstarling\u003c\/span\u003e\u003c\/a\u003e wrote:\u003c\/div\u003e\n\u003cdiv class=\"remarkup-reply-body\"\u003e\u003cp\u003eOK, I'm adding PHP execution to the service.\u003c\/p\u003e\u003c\/div\u003e\n\u003c\/blockquote\u003e\n\n\u003cp\u003eAm I correct to assume that the PHP execution mode will just be a shorthand for something like \u003ctt class=\"remarkup-monospaced\"\u003ephp -r 'echo "Hello";'\u003c\/tt\u003e?\u003c\/p\u003e\u003c\/div\u003e\n\u003c\/blockquote\u003e\n\n\u003cp\u003eNo, I refactored the server so that it has actions, and the actions are called "shell" which runs a shell command, and "call" which calls a PHP function with specified parameters. They share a TemporaryDirectoryManager and input file handling. The "call" action also \u003ctt class=\"remarkup-monospaced\"\u003erequire\u003c\/tt\u003es a list of PHP input files, so that's how you define the function you're calling. I preferred this over an eval() endpoint since I didn't like the idea of encoding function call parameters as PHP code. This way, they are encoded with JSON. On the client side, I imagine you will be able to specify a class name, which will be added to the file list to transfer using ReflectionClass::getFileName().\u003c\/p\u003e\n\n\u003cp\u003eThe output formats are broadly similar, but with "shell" there are output files and JSON, whereas with "call" there is just JSON, being the serialized return value.\u003c\/p\u003e\n\n\u003cp\u003eI don't think it still makes sense for it to all be under BoxedCommand. It's now two things: remote shell and PHP RPC. Maybe something like\u003c\/p\u003e\n\n\u003cdiv class=\"remarkup-code-block\" data-code-lang=\"php\" data-sigil=\"remarkup-code-block\"\u003e\u003cpre class=\"remarkup-code\"\u003e\u003cspan class=\"nv\"\u003e$rpcService\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"nc\" data-symbol-name=\"MediaWikiServices\"\u003eMediaWikiServices\u003c\/span\u003e\u003cspan class=\"o\"\u003e::\u003c\/span\u003e\u003cspan class=\"nf\" data-symbol-context=\"MediaWikiServices\" data-symbol-name=\"getInstance\"\u003egetInstance\u003c\/span\u003e\u003cspan class=\"o\"\u003e()->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"getPhpRpc\"\u003egetPhpRpc\u003c\/span\u003e\u003cspan class=\"o\"\u003e();\u003c\/span\u003e\n\u003cspan class=\"nv\"\u003e$result\u003c\/span\u003e \u003cspan class=\"o\"\u003e=\u003c\/span\u003e \u003cspan class=\"nv\"\u003e$rpcService\u003c\/span\u003e\u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"newCallBuilder\"\u003enewCallBuilder\u003c\/span\u003e\u003cspan class=\"o\"\u003e()\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"classes\"\u003eclasses\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"nc\" data-symbol-name=\"MyRpc\"\u003eMyRpc\u003c\/span\u003e\u003cspan class=\"o\"\u003e::\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-context=\"MyRpc\" data-symbol-name=\"class\"\u003eclass\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"function\"\u003efunction\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"o\"\u003e[\u003c\/span\u003e \u003cspan class=\"nc\" data-symbol-name=\"MyRpc\"\u003eMyRpc\u003c\/span\u003e\u003cspan class=\"o\"\u003e::\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-context=\"MyRpc\" data-symbol-name=\"class\"\u003eclass\u003c\/span\u003e\u003cspan class=\"o\"\u003e,\u003c\/span\u003e \u003cspan class=\"s1\"\u003e'execute'\u003c\/span\u003e \u003cspan class=\"o\"\u003e]\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"params\"\u003eparams\u003c\/span\u003e\u003cspan class=\"o\"\u003e(\u003c\/span\u003e \u003cspan class=\"mi\"\u003e1\u003c\/span\u003e\u003cspan class=\"o\"\u003e,\u003c\/span\u003e \u003cspan class=\"mi\"\u003e2\u003c\/span\u003e\u003cspan class=\"o\"\u003e,\u003c\/span\u003e \u003cspan class=\"mi\"\u003e3\u003c\/span\u003e \u003cspan class=\"o\"\u003e)\u003c\/span\u003e\n \u003cspan class=\"o\"\u003e->\u003c\/span\u003e\u003cspan class=\"na\" data-symbol-name=\"execute\"\u003eexecute\u003c\/span\u003e\u003cspan class=\"o\"\u003e();\u003c\/span\u003e\u003c\/pre\u003e\u003c\/div\u003e\n\n\u003cp\u003eWhere $result is just the return value of MyRpc::execute(1, 2, 3).\u003c\/p\u003e\n\n\u003cp\u003eUnderlying the BoxedCommand and PHP RPC abstractions there would be a shared client, perhaps still called Shellbox.\u003c\/p\u003e\n\n\u003cp\u003eIf the name is definitely OK then I can make a repository for it and upload a WIP patch. Currently in my Shellbox directory I have a plausible-looking server with input\/output file handling and HMAC authentication. The "call" endpoint is basically complete (with 25 lines of code) whereas the "shell" endpoint is a stub. In a local MediaWiki branch, I have drafts of the BoxedCommand interfaces and some refactoring for the Command\/Executor split. Next I was going to write a client utility which will generate the HMAC-signed request body. Then I would stop procrastinating on Command\/Executor and finish that off.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_299\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/v5wmnfiaelrd6nztxd3a\/PHID-FILE-s57znldbv3qchtewuryd\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/daniel\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-badges\"\u003e\u003cul class=\"phui-badge-flex-view grouped flex-view-collapsed \"\u003e\u003cli class=\"phui-badge-flex-item\"\u003e\u003ca class=\"phui-badge-mini phui-badge-mini-indigo \" href=\"\/badges\/view\/14\/\" data-sigil=\"has-tooltip\" data-meta=\"0_297\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-empire\" data-meta=\"0_298\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6405862\" id=\"6405862\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_296\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/daniel\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_85\"\u003edaniel\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003eEdited\u003cspan class=\"visual-only\" aria-hidden=\"true\"\u003e \u00b7 \u003c\/span\u003e\u003ca href=\"#6405862\" data-sigil=\"has-tooltip\" data-meta=\"0_295\"\u003e\u003cspan class=\"screen-only\"\u003eAug 24 2020, 12:06 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-24 12:06:52 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_293\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_294\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_86\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cblockquote\u003e\u003cp\u003eThe "call" action also requires a list of PHP input files, so that's how you define the function you're calling.\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eSo the PHP code is send along with the command every time the command is executed? That seems wasteful, but changing that would change the paradigm, or require more complex interactions between the services... probably best left as an optimization for later.\u003c\/p\u003e\n\n\u003cp\u003e"Shellbox" seems fine as a name.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_308\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/wlk2r6kir2zwmeqxom2a\/PHID-FILE-uxcr3iugxbqeyo2uxyqp\/7e3e53-alphanumeric_lato-dark_J.png-255%2C255%2C255%2C0.4.png)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/JMeybohm\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6405988\" id=\"6405988\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_307\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/JMeybohm\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_87\"\u003eJMeybohm\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6405988\" data-sigil=\"has-tooltip\" data-meta=\"0_306\"\u003e\u003cspan class=\"screen-only\"\u003eAug 24 2020, 12:39 PM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-24 12:39:22 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_304\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_305\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_88\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cblockquote class=\"remarkup-reply-block\"\u003e\n\u003cdiv class=\"remarkup-reply-head\"\u003eIn \u003ca href=\"\/T260330#6405691\" class=\"phui-tag-view phui-tag-type-object \" data-sigil=\"hovercard\" data-meta=\"0_22\"\u003e\u003cspan class=\"phui-tag-core-closed\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-object\"\u003eT260330#6405691\u003c\/span\u003e\u003c\/span\u003e\u003c\/a\u003e, \u003ca href=\"\/p\/Joe\/\" class=\"phui-tag-view phui-tag-type-person \" data-sigil=\"hovercard\" data-meta=\"0_23\"\u003e\u003cspan class=\"phui-tag-core phui-tag-color-person\"\u003e@Joe\u003c\/span\u003e\u003c\/a\u003e wrote:\u003c\/div\u003e\n\u003cdiv class=\"remarkup-reply-body\"\u003e\u003cp\u003eMy current idea is that we will run these "nanoservices" as normal kubernetes services, so the containers will run until they get killed for an external reason, and be restarted if that happens. The reason for this is exactly that the startup time is too large (you also have to add the work of the kubernetes scheduler). The issue with that is of course that\u003c\/p\u003e\n\n\u003cblockquote\u003e\u003cp\u003eIf containers are persistent and serve multiple requests, then we should consider whether a malicious command could become persistent within the container, attacking subsequent commands. That's not possible with firejail because it shuts down the per-command container with kill(-1, SIGKILL).\u003c\/p\u003e\u003c\/blockquote\u003e\n\n\u003cp\u003eThis holds true. I'm still unsure how to balance it besides "the container is an empty shell anyways, which will hold no credentials nor any sensible data".\u003c\/p\u003e\u003c\/div\u003e\n\u003c\/blockquote\u003e\n\n\u003cp\u003eDepending on the request volume (and the number of replicas) it might also be possible to kill the container (not the pod) after every request (via a livenessProbe?). If the Pod does not die, the container restart should be pretty fast as no rescheduling is done.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-spacer\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-shell\" data-sigil=\"transaction anchor-container\" data-meta=\"0_317\"\u003e\u003cdiv class=\"phui-timeline-event-view phui-timeline-major-event\"\u003e\u003cdiv class=\"phui-timeline-content\"\u003e\u003ca style=\"background-image: url(https:\/\/phab.wmfusercontent.org\/file\/data\/xgl3wy55ovinfnucvwhx\/PHID-FILE-zocnksypiqutzf5oubpi\/profile)\" class=\"visual-only phui-timeline-image\" href=\"\/p\/tstarling\/\" aria-hidden=\"true\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-wedge\" style=\"\"\u003e\u003c\/div\u003e\u003cdiv class=\"phui-timeline-group\"\u003e\u003cdiv class=\"phui-timeline-inner-content\"\u003e\u003ca name=\"6408193\" id=\"6408193\" class=\"phabricator-anchor-view\"\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-title phui-timeline-title-with-icon phui-timeline-title-with-menu\"\u003e\u003cspan class=\"phui-timeline-icon-fill\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-comment phui-timeline-icon\" data-meta=\"0_316\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/span\u003e\u003ca href=\"\/p\/tstarling\/\" class=\"phui-handle phui-link-person\" data-sigil=\"hovercard\" data-meta=\"0_89\"\u003etstarling\u003c\/a\u003e added a comment.\u003cspan class=\"phui-timeline-extra\"\u003e\u003ca href=\"#6408193\" data-sigil=\"has-tooltip\" data-meta=\"0_315\"\u003e\u003cspan class=\"screen-only\"\u003eAug 25 2020, 4:37 AM\u003c\/span\u003e\u003cspan class=\"print-only\" aria-hidden=\"true\"\u003e2020-08-25 04:37:31 (UTC+0)\u003c\/span\u003e\u003c\/a\u003e\u003c\/span\u003e\u003c\/div\u003e\u003ca href=\"#\" class=\"phui-timeline-menu\" aria-haspopup=\"true\" aria-expanded=\"false\" data-sigil=\"phui-dropdown-menu\" data-meta=\"0_313\"\u003e\u003cspan class=\"aural-only\"\u003eComment Actions\u003c\/span\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-caret-down\" data-meta=\"0_314\" aria-hidden=\"true\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cdiv class=\"phui-timeline-core-content\"\u003e\u003cspan class=\"transaction-comment\" data-sigil=\"transaction-comment\" data-meta=\"0_90\"\u003e\u003cdiv class=\"phabricator-remarkup\"\u003e\u003cp\u003eHas anyone got an idea for giving the HMAC key to the server without allowing the command to have access to it? Otherwise an attacker can use a command to exfiltrate the key and then spoof requests. If it's not possible, maybe we should think about asymmetric encryption.\u003c\/p\u003e\u003c\/div\u003e\u003c\/span\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e"},"javelin_metadata":[{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-enwzojhbcyxuu2kj754m"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-USER-jzbjfcs2csloltie4voe","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-dimrvvugv53uaomqkgn6"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-dimrvvugv53uaomqkgn6"}},{"hovercardSpec":{"objectPHID":"PHID-USER-fdo23otm6ztt674vjqko","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-USER-fdo23otm6ztt674vjqko","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-dimrvvugv53uaomqkgn6"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-dimrvvugv53uaomqkgn6"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-USER-5dqihbanu3caaj7pigif","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-USER-fdo23otm6ztt674vjqko","contextPHID":"PHID-TASK-afcm6wi4p3abffizlu5q"}},{"hovercardSpec":{"objectPHID":"PHID-USER-fdo23otm6ztt674vjqko"}},{"hovercardSpec":{"objectPHID":"PHID-USER-zwu7g4ktdljroehcge7p"}},{"hovercardSpec":{"objectPHID":"PHID-USER-u7w6n5ecde66oujx33pe"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-kupmx5hl6532yj36ilir"}},{"hovercardSpec":{"objectPHID":"PHID-USER-wr3pospifdaxghmtobvr"}},{"hovercardSpec":{"objectPHID":"PHID-USER-jzbjfcs2csloltie4voe"}},{"hovercardSpec":{"objectPHID":"PHID-USER-dp5h2v3xwdzdh4dug36u"}},{"hovercardSpec":{"objectPHID":"PHID-PCOL-bwlulsay32453cbbuwim"}},{"hovercardSpec":{"objectPHID":"PHID-PCOL-7gz3642e4oidtfpwfcoj"}},{"hovercardSpec":{"objectPHID":"PHID-PROJ-ffms22arq2fzb25pcbwn"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"phid":"PHID-XACT-TASK-2ja642qb45upxoh"},{"hovercardSpec":{"objectPHID":"PHID-USER-dp5h2v3xwdzdh4dug36u"}},{"hovercardSpec":{"objectPHID":"PHID-PCOL-7gz3642e4oidtfpwfcoj"}},{"hovercardSpec":{"objectPHID":"PHID-PCOL-bwlulsay32453cbbuwim"}},{"hovercardSpec":{"objectPHID":"PHID-PROJ-ffms22arq2fzb25pcbwn"}},{"hovercardSpec":{"objectPHID":"PHID-USER-hrcsuxxosiyjqpef64tc"}},{"hovercardSpec":{"objectPHID":"PHID-TASK-dimrvvugv53uaomqkgn6"}},{"hovercardSpec":{"objectPHID":"PHID-USER-hrcsuxxosiyjqpef64tc"}},{"hovercardSpec":{"objectPHID":"PHID-USER-ctchvhisqfvk4rz7nt7d"}},{"hovercardSpec":{"objectPHID":"PHID-USER-dccizlq7dtc2zihfk7cd"}},{"hovercardSpec":{"objectPHID":"PHID-USER-ztjg3hghf3kwdc2pd6se"}},{"hovercardSpec":{"objectPHID":"PHID-USER-ztjg3hghf3kwdc2pd6se"}},{"hovercardSpec":{"objectPHID":"PHID-PROJ-va37kiwzbgywahiczwjk"}},{"hovercardSpec":{"objectPHID":"PHID-PROJ-2b7oz62ylk3jk4aus262"}},{"hovercardSpec":{"objectPHID":"PHID-USER-ztjg3hghf3kwdc2pd6se"}},{"hovercardSpec":{"objectPHID":"PHID-PCOL-r5kuf624ie7dcnsf4ri6"}},{"hovercardSpec":{"objectPHID":"PHID-PCOL-oxaerhfqibzpog4ynjgb"}},{"hovercardSpec":{"objectPHID":"PHID-PROJ-va37kiwzbgywahiczwjk"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"hovercardSpec":{"objectPHID":"PHID-USER-6b6w5qogf4deywgbkuzs"}},{"hovercardSpec":{"objectPHID":"PHID-USER-jzbjfcs2csloltie4voe"}},{"phid":"PHID-XACT-TASK-p3pwtlajnkvapjo"},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"phid":"PHID-XACT-TASK-pmpmess3c3ynxca"},{"hovercardSpec":{"objectPHID":"PHID-USER-jzbjfcs2csloltie4voe"}},{"phid":"PHID-XACT-TASK-y3wt56mgyngmd4i"},{"hovercardSpec":{"objectPHID":"PHID-USER-u7w6n5ecde66oujx33pe"}},{"hovercardSpec":{"objectPHID":"PHID-USER-ctchvhisqfvk4rz7nt7d"}},{"phid":"PHID-XACT-TASK-qtkw2qnzadxtxd3"},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"phid":"PHID-XACT-TASK-oz3ktj6osjav3gg"},{"hovercardSpec":{"objectPHID":"PHID-USER-fdo23otm6ztt674vjqko"}},{"phid":"PHID-XACT-TASK-b5s7fjp67zsyuu4"},{"hovercardSpec":{"objectPHID":"PHID-USER-c4xszutxtrvtj73h3rns"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"phid":"PHID-XACT-TASK-wz64wptrg5uotdr"},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"phid":"PHID-XACT-TASK-sppu3gjy6ox53rt"},{"phid":"PHID-XACT-TASK-mr53z6y5a7swcwi"},{"hovercardSpec":{"objectPHID":"PHID-USER-5dqihbanu3caaj7pigif"}},{"hovercardSpec":{"objectPHID":"PHID-USER-5dqihbanu3caaj7pigif"}},{"phid":"PHID-XACT-TASK-ybzsicm6onxtj7j"},{"hovercardSpec":{"objectPHID":"PHID-USER-fdo23otm6ztt674vjqko"}},{"phid":"PHID-XACT-TASK-6ojtb5yiahl4qmj"},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"phid":"PHID-XACT-TASK-qbogmgdyhjgpsoc"},{"hovercardSpec":{"objectPHID":"PHID-USER-5dqihbanu3caaj7pigif"}},{"phid":"PHID-XACT-TASK-6zv246gtqggofi2"},{"hovercardSpec":{"objectPHID":"PHID-USER-zwu7g4ktdljroehcge7p"}},{"phid":"PHID-XACT-TASK-ytgy4hd4zgtzlra"},{"hovercardSpec":{"objectPHID":"PHID-USER-k6tmz5ylx4rzfl3bitse"}},{"phid":"PHID-XACT-TASK-ccrdxmhagtdsecu"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-2kk5tia2hzqdlgi","anchor":"6382080"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-x5m5rzi2q4mktus","anchor":"6382092"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-e6zfjd6ytqckud7","anchor":"6382118"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-cnz6iowybj6aovv","anchor":"6387703"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-d5okeh64ukev2e7","anchor":"6388077"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-esdfvzeadqiw26m","anchor":"6389940"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-pog3day7hrdjfac","anchor":"6391404"},{"tip":"Via Web"},[],[],{"phid":"PHID-XACT-TASK-tpags3z74s2ya2g","anchor":"6392671"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-2ja642qb45upxoh\/","ref":"T260330#6392683"},[],{"anchor":"6392683"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_1\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_116\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_117\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_3\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-2ja642qb45upxoh\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_118\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_119\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-cjy2fpmbkmb3pmz","anchor":"6392683"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-eobtt4v4p4y625k","anchor":"6392687"},{"tip":"Via Web"},[],[],{"phid":"PHID-XACT-TASK-xrfclozoexn5fpw","anchor":"6392691"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-p3ncgnkcjp73akw","anchor":"6392695"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-xw3ercau4sldtjl","anchor":"6393599"},{"tip":"Via Web"},[],[],[],{"phid":"PHID-XACT-TASK-ylgpkutwfzrno6s","anchor":"6393794"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-57r6qnnxd3rlyj4","anchor":"6395250"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-bn2odmy5zrzvnhg","anchor":"6395251"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-p3pwtlajnkvapjo\/","ref":"T260330#6396222"},[],{"anchor":"6396222"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_5\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_149\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_150\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_7\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-p3pwtlajnkvapjo\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_151\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_152\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"tip":"Deployment Training Graduate","align":"E","size":300},[],{"tip":"Mentor","align":"E","size":300},[],{"phid":"PHID-XACT-TASK-p3pwtlajnkvapjo","anchor":"6396222"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-pmpmess3c3ynxca\/","ref":"T260330#6396259"},[],{"anchor":"6396259"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_9\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_162\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_163\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_11\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-pmpmess3c3ynxca\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_164\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_165\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-pmpmess3c3ynxca","anchor":"6396259"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-y3wt56mgyngmd4i\/","ref":"T260330#6396291"},[],{"anchor":"6396291"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_13\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_171\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_172\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_15\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-y3wt56mgyngmd4i\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_173\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_174\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"tip":"Deployment Training Graduate","align":"E","size":300},[],{"tip":"Mentor","align":"E","size":300},[],{"phid":"PHID-XACT-TASK-y3wt56mgyngmd4i","anchor":"6396291"},{"tip":"Via Web"},[],[],{"phid":"PHID-XACT-TASK-xynllx6vuuw34xn","anchor":"6396703"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-qtkw2qnzadxtxd3\/","ref":"T260330#6398816"},[],{"anchor":"6398816"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_17\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_188\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_189\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_19\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-qtkw2qnzadxtxd3\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_190\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_191\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"tip":"Web Perf Hero","align":"E","size":300},[],{"tip":"Rat Catcher","align":"E","size":300},[],{"phid":"PHID-XACT-TASK-qtkw2qnzadxtxd3","anchor":"6398816"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-oz3ktj6osjav3gg\/","ref":"T260330#6398851"},[],{"anchor":"6398851"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_21\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_201\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_202\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_23\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-oz3ktj6osjav3gg\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_203\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_204\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-oz3ktj6osjav3gg","anchor":"6398851"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-b5s7fjp67zsyuu4\/","ref":"T260330#6399137"},[],{"anchor":"6399137"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_25\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_210\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_211\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_27\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-b5s7fjp67zsyuu4\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_212\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_213\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"tip":"Web Perf Hero","align":"E","size":300},[],{"phid":"PHID-XACT-TASK-b5s7fjp67zsyuu4","anchor":"6399137"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-aypwfpap574iglh","anchor":"6400041"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-wz64wptrg5uotdr\/","ref":"T260330#6401694"},[],{"anchor":"6401694"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_29\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_224\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_225\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_31\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-wz64wptrg5uotdr\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_226\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_227\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-wz64wptrg5uotdr","anchor":"6401694"},{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-elqbrhr3jsf2wax","anchor":"6401748"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-sppu3gjy6ox53rt\/","ref":"T260330#6401750"},[],{"anchor":"6401750"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_33\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_236\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_237\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_35\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-sppu3gjy6ox53rt\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_238\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_239\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-sppu3gjy6ox53rt","anchor":"6401750"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-mr53z6y5a7swcwi\/","ref":"T260330#6405293"},[],{"anchor":"6405293"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_37\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_245\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_246\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_39\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-mr53z6y5a7swcwi\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_247\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_248\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"tip":"Nerd Sniper","align":"E","size":300},[],{"phid":"PHID-XACT-TASK-mr53z6y5a7swcwi","anchor":"6405293"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-ybzsicm6onxtj7j\/","ref":"T260330#6405301"},[],{"anchor":"6405301"},[],[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_41\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_256\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_257\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_43\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-ybzsicm6onxtj7j\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_258\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_259\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_45\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/history\/PHID-XACT-TASK-ybzsicm6onxtj7j\/\" class=\"phabricator-action-view-item\" data-sigil=\"workflow\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-list phabricator-action-view-icon\" data-meta=\"0_260\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Edit History\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"tip":"Nerd Sniper","align":"E","size":300},[],{"phid":"PHID-XACT-TASK-ybzsicm6onxtj7j","anchor":"6405301"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-6ojtb5yiahl4qmj\/","ref":"T260330#6405691"},[],{"anchor":"6405691"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_47\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_268\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_269\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_49\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-6ojtb5yiahl4qmj\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_270\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_271\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"tip":"Web Perf Hero","align":"E","size":300},[],{"phid":"PHID-XACT-TASK-6ojtb5yiahl4qmj","anchor":"6405691"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-qbogmgdyhjgpsoc\/","ref":"T260330#6405702"},[],{"anchor":"6405702"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_51\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_279\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_280\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_53\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-qbogmgdyhjgpsoc\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_281\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_282\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-qbogmgdyhjgpsoc","anchor":"6405702"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-6zv246gtqggofi2\/","ref":"T260330#6405862"},[],{"anchor":"6405862"},[],[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_55\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_288\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_289\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_57\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-6zv246gtqggofi2\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_290\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_291\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_59\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/history\/PHID-XACT-TASK-6zv246gtqggofi2\/\" class=\"phabricator-action-view-item\" data-sigil=\"workflow\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-list phabricator-action-view-icon\" data-meta=\"0_292\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Edit History\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"tip":"Nerd Sniper","align":"E","size":300},[],{"phid":"PHID-XACT-TASK-6zv246gtqggofi2","anchor":"6405862"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-ytgy4hd4zgtzlra\/","ref":"T260330#6405988"},[],{"anchor":"6405988"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_61\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_300\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_301\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_63\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-ytgy4hd4zgtzlra\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_302\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_303\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-ytgy4hd4zgtzlra","anchor":"6405988"},{"targetID":"UQ0_1","uri":"\/transactions\/quote\/PHID-XACT-TASK-ccrdxmhagtdsecu\/","ref":"T260330#6408193"},[],{"anchor":"6408193"},[],{"items":"\u003cul class=\"phabricator-action-list-view \"\u003e\u003cli id=\"UQ0_65\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"#\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-quote\" data-meta=\"0_309\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-quote-left phabricator-action-view-icon\" data-meta=\"0_310\" aria-hidden=\"true\"\u003e\u003c\/span\u003eQuote Comment\u003c\/a\u003e\u003c\/li\u003e\u003cli id=\"UQ0_67\" class=\"phabricator-action-view phabricator-action-view-href action-has-icon\" style=\"\"\u003e\u003ca href=\"\/transactions\/raw\/PHID-XACT-TASK-ccrdxmhagtdsecu\/\" class=\"phabricator-action-view-item\" data-sigil=\"transaction-raw\" data-meta=\"0_311\"\u003e\u003cspan class=\"visual-only phui-icon-view phui-font-fa fa-code phabricator-action-view-icon\" data-meta=\"0_312\" aria-hidden=\"true\"\u003e\u003c\/span\u003eView Raw Remarkup\u003c\/a\u003e\u003c\/li\u003e\u003c\/ul\u003e"},[],{"tip":"Via Web"},[],{"phid":"PHID-XACT-TASK-ccrdxmhagtdsecu","anchor":"6408193"}],"javelin_behaviors":{"phui-hovercards":[],"phabricator-watch-anchor":[],"phabricator-tooltips":[],"phui-dropdown-menu":[]},"javelin_resources":["https:\/\/phab.wmfusercontent.org\/res\/defaultX\/phabricator\/2eeda9e0\/core.pkg.js","https:\/\/phab.wmfusercontent.org\/res\/defaultX\/phabricator\/98e6504a\/rsrc\/externals\/javelin\/core\/init.js","https:\/\/phab.wmfusercontent.org\/res\/defaultX\/phabricator\/968d91ee\/core.pkg.css","https:\/\/phab.wmfusercontent.org\/res\/defaultX\/phabricator\/666e25ad\/rsrc\/css\/phui\/phui-badge.css"]}