{"owner":"LizardByte","repo":"Sunshine","hasSkills":true,"totalSkillsCount":2,"totalTokensCount":1807,"categories":["root-instruction","project-spec"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md","docs/api.md"],"skills":{"AGENTS.md":"## Build and tests\n\nOn Windows we use msys2 and ucrt64 to compile.\nPrefix Windows build and test commands with `C:\\msys64\\msys2_shell.cmd -defterm -here -no-start -ucrt64 -c`.\n\nPrefix build directories with `cmake-build-`.\n\nThe test executable is named `test_sunshine` and will be located inside the `tests` directory within\nthe build directory.\n\nThe project uses gtest as a test framework.\n\nSunshine tests must include `tests/tests_common.h` using the appropriate relative path, rather than including\n`<gtest/gtest.h>` directly. The common header provides GoogleTest through the shared test support and makes\n`TEST` use `BaseTest`, including its output capture and shared setup/teardown.\n\nGroup test headers first under `// test includes`, followed by `// standard includes`, `// lib includes`, and\n`// local includes`, with a blank line between groups. Put shared test helpers in the test group, and omit empty\ngroups. Keep platform-specific headers and their group comments inside the appropriate preprocessor guards.\nWhen a test depends on a particular include order, preserve that order and explain the dependency in a comment;\ndo not move the common header ahead of headers whose first-include behavior is being tested.\n\nAdd or update regression tests for new or modified source-code methods and behavior.\nTarget 100% coverage on changed source code.\n\nThe regression-test requirement does not apply to build-system files, such as CMake scripts and dependency configuration.\nValidate build-system changes with appropriate configuration, build, and lint checks.\nDo not add dedicated build-system regression-test projects or fixtures for these changes.\n\n## Python tooling and formatting\n\nFrom the repository root, run `uv sync --locked` to create or refresh `.venv` from `pyproject.toml` and `uv.lock`.\nRe-run it after switching branches or changing either file or the `third-party/lizardbyte-common` submodule.\nAfter changing dependency declarations or the submodule revision, run `uv lock` before syncing.\n\nAfter native code changes, run `uv run --locked lb-update-clang-format` from the repository root. The command is\nprovided by `third-party/lizardbyte-common`; inspect the resulting diff for unrelated formatting changes.\n\n## Code style and documentation\n\nWhen adding localization do not update any language other than `en`. This also means to exclude en-US or other variants.\n\nAlways add or update doxygen documentation.\n\nThe project requires that everything be documented in doxygen or the build will fail.\n\nPrimary doxygen comments should be done like so:\n\n```cpp\n  /**\n   * @brief Describe the function, structure, etc.\n   *\n   * @param my_param Describe the parameter.\n   * @return Describe the return.\n   */\n```\n\nInline doxygen comments should use `///< ...` instead of `/**< ... */`.\n\nAlways follow the style guidelines defined in .clang-format for c/c++ code.\n\nDo not add decorative separator comments, including dashed banners that label groups of tests. Use descriptive\ntest names and code structure to show the grouping instead.\n\n## Issues and pull requests\n\nWhen asked to create an issue or pull request, use the templates provided by the LizardByte/.github repo or\nLizardByte/Sunshine repo, with the Sunshine templates taking precedence if both exist. At the end of the issue\nor pull request body, add an attribution naming the AI agent, model, and thinking level used to generate it.\nRepeat that attribution in a separate comment on the created issue or pull request. For example:\n\n```\n> This issue was generated by ChatGPT 6 Sol, extra high thinking level\n```\n\nWhen asked to create an issue, do only enough investigation to verify and accurately describe the problem unless the\nuser also asks for an investigation. Keep the issue concise: state the observed behavior, expected behavior, and\nreproduction steps or evidence when available. Do not include an exhaustive root-cause analysis or implementation\nplan in the issue. This limit applies only to creating issues; investigate or fix issues fully when asked.\n\n## Code Review Rules\n\nCheck new and modified tests for the common-header and include-group conventions above. Request\n`tests_common.h` instead of direct GoogleTest includes, and ensure shared test helpers are in the test include\ngroup. Verify any documented include-order dependency before asking the author to reorder headers.\n\nReport concrete issues introduced by the change that the contributor can address. For each finding, explain the\ntriggering condition, impact, and a practical fix; point to the relevant code or test. Keep workflow status separate\nfrom code findings.\n\nIf GitHub Actions workflows are queued for maintainer approval, or a dependent check times out before its job can run,\ndo not leave an inline comment, request changes, or ask the contributor to run the workflows. The maintainer controls\napproval. If the missing results materially limit the review, mention that once in the review summary as a verification\nlimit for the maintainer. Review actual failed checks for change-related problems when their logs are available.\n\nFor pull request reviews, verify the current PR head and mergeability against its target branch. If conflicts are\nconfirmed, tell the author in the review summary that the PR needs to be rebased and the conflicts resolved before\nmerging. Do not infer conflicts from an unknown or pending mergeability status.\n\nWhen approving a pull request, the approval itself is sufficient. Do not add a comment solely to accompany it.\n","docs/api.md":"# API\n\nSunshine has a RESTful API which can be used to interact with the service.\n\nUnless otherwise specified, authentication is required for all API calls. You can authenticate using\nbasic authentication with the admin username and password.\n\n## CSRF Protection\n\nState-changing API endpoints (POST, DELETE) are protected against Cross-Site Request Forgery (CSRF) attacks.\n\n**For Web Browsers:**\n- Requests from same-origin (configured via `csrf_allowed_origins`) are automatically allowed\n- Cross-origin requests require a CSRF token\n\n**For Non-Browser Applications:**\n- Non-browser clients (e.g. `curl`, scripts, custom apps) are **exempt** from CSRF protection\n- CSRF attacks require a browser to silently attach credentials to a cross-origin request — this threat\n  does not apply to non-browser clients that explicitly provide credentials with every request\n- Requests with no `Origin` or `Referer` header (as is typical for non-browser clients) are automatically\n  allowed without a CSRF token\n\n**Example (browser-equivalent cross-origin request):**\n```bash\n# Get CSRF token\ncurl -u user:pass https://localhost:47990/api/csrf-token\n\n# Use token in request\ncurl -u user:pass -H \"X-CSRF-Token: your_token_here\" \\\n  -X POST https://localhost:47990/api/restart\n```\n\n@htmlonly\n<script src=\"api.js\"></script>\n@endhtmlonly\n\n## GET /api/csrf-token\n@copydoc confighttp::getCSRFToken()\n\n## GET /api/apps\n@copydoc confighttp::getApps()\n\n## POST /api/apps\n@copydoc confighttp::saveApp()\n\n## POST /api/apps/close\n@copydoc confighttp::closeApp()\n\n## DELETE /api/apps/{index}\n@copydoc confighttp::deleteApp()\n\n## GET /api/browse\n@copydoc confighttp::browseDirectory()\n\n## GET /api/clients/list\n@copydoc confighttp::getClients()\n\n## POST /api/clients/unpair\n@copydoc confighttp::unpair()\n\n## POST /api/clients/unpair-all\n@copydoc confighttp::unpairAll()\n\n## POST /api/clients/update\n@copydoc confighttp::updateClient()\n\n## GET /api/config\n@copydoc confighttp::getConfig()\n\n## GET /api/configLocale\n@copydoc confighttp::getLocale()\n\n## POST /api/config\n@copydoc confighttp::saveConfig()\n\n## GET /api/covers/{index}\n@copydoc confighttp::getCover()\n\n## POST /api/covers/upload\n@copydoc confighttp::uploadCover()\n\n## GET /api/logs\n@copydoc confighttp::getLogs()\n\n## POST /api/password\n@copydoc confighttp::savePassword()\n\n## POST /api/pin\n@copydoc confighttp::savePin()\n\n## POST /api/reset-display-device-persistence\n@copydoc confighttp::resetDisplayDevicePersistence()\n\n## POST /api/reset-portal-token\n@copydoc confighttp::resetPortalToken()\n\n## POST /api/restart\n@copydoc confighttp::restart()\n\n## GET /api/virtual-input/status\n@copydoc confighttp::getVirtualInputStatus()\n"},"files":{"AGENTS.md":"## Build and tests\n\nOn Windows we use msys2 and ucrt64 to compile.\nPrefix Windows build and test commands with `C:\\msys64\\msys2_shell.cmd -defterm -here -no-start -ucrt64 -c`.\n\nPrefix build directories with `cmake-build-`.\n\nThe test executable is named `test_sunshine` and will be located inside the `tests` directory within\nthe build directory.\n\nThe project uses gtest as a test framework.\n\nSunshine tests must include `tests/tests_common.h` using the appropriate relative path, rather than including\n`<gtest/gtest.h>` directly. The common header provides GoogleTest through the shared test support and makes\n`TEST` use `BaseTest`, including its output capture and shared setup/teardown.\n\nGroup test headers first under `// test includes`, followed by `// standard includes`, `// lib includes`, and\n`// local includes`, with a blank line between groups. Put shared test helpers in the test group, and omit empty\ngroups. Keep platform-specific headers and their group comments inside the appropriate preprocessor guards.\nWhen a test depends on a particular include order, preserve that order and explain the dependency in a comment;\ndo not move the common header ahead of headers whose first-include behavior is being tested.\n\nAdd or update regression tests for new or modified source-code methods and behavior.\nTarget 100% coverage on changed source code.\n\nThe regression-test requirement does not apply to build-system files, such as CMake scripts and dependency configuration.\nValidate build-system changes with appropriate configuration, build, and lint checks.\nDo not add dedicated build-system regression-test projects or fixtures for these changes.\n\n## Python tooling and formatting\n\nFrom the repository root, run `uv sync --locked` to create or refresh `.venv` from `pyproject.toml` and `uv.lock`.\nRe-run it after switching branches or changing either file or the `third-party/lizardbyte-common` submodule.\nAfter changing dependency declarations or the submodule revision, run `uv lock` before syncing.\n\nAfter native code changes, run `uv run --locked lb-update-clang-format` from the repository root. The command is\nprovided by `third-party/lizardbyte-common`; inspect the resulting diff for unrelated formatting changes.\n\n## Code style and documentation\n\nWhen adding localization do not update any language other than `en`. This also means to exclude en-US or other variants.\n\nAlways add or update doxygen documentation.\n\nThe project requires that everything be documented in doxygen or the build will fail.\n\nPrimary doxygen comments should be done like so:\n\n```cpp\n  /**\n   * @brief Describe the function, structure, etc.\n   *\n   * @param my_param Describe the parameter.\n   * @return Describe the return.\n   */\n```\n\nInline doxygen comments should use `///< ...` instead of `/**< ... */`.\n\nAlways follow the style guidelines defined in .clang-format for c/c++ code.\n\nDo not add decorative separator comments, including dashed banners that label groups of tests. Use descriptive\ntest names and code structure to show the grouping instead.\n\n## Issues and pull requests\n\nWhen asked to create an issue or pull request, use the templates provided by the LizardByte/.github repo or\nLizardByte/Sunshine repo, with the Sunshine templates taking precedence if both exist. At the end of the issue\nor pull request body, add an attribution naming the AI agent, model, and thinking level used to generate it.\nRepeat that attribution in a separate comment on the created issue or pull request. For example:\n\n```\n> This issue was generated by ChatGPT 6 Sol, extra high thinking level\n```\n\nWhen asked to create an issue, do only enough investigation to verify and accurately describe the problem unless the\nuser also asks for an investigation. Keep the issue concise: state the observed behavior, expected behavior, and\nreproduction steps or evidence when available. Do not include an exhaustive root-cause analysis or implementation\nplan in the issue. This limit applies only to creating issues; investigate or fix issues fully when asked.\n\n## Code Review Rules\n\nCheck new and modified tests for the common-header and include-group conventions above. Request\n`tests_common.h` instead of direct GoogleTest includes, and ensure shared test helpers are in the test include\ngroup. Verify any documented include-order dependency before asking the author to reorder headers.\n\nReport concrete issues introduced by the change that the contributor can address. For each finding, explain the\ntriggering condition, impact, and a practical fix; point to the relevant code or test. Keep workflow status separate\nfrom code findings.\n\nIf GitHub Actions workflows are queued for maintainer approval, or a dependent check times out before its job can run,\ndo not leave an inline comment, request changes, or ask the contributor to run the workflows. The maintainer controls\napproval. If the missing results materially limit the review, mention that once in the review summary as a verification\nlimit for the maintainer. Review actual failed checks for change-related problems when their logs are available.\n\nFor pull request reviews, verify the current PR head and mergeability against its target branch. If conflicts are\nconfirmed, tell the author in the review summary that the PR needs to be rebased and the conflicts resolved before\nmerging. Do not infer conflicts from an unknown or pending mergeability status.\n\nWhen approving a pull request, the approval itself is sufficient. Do not add a comment solely to accompany it.\n","docs/api.md":"# API\n\nSunshine has a RESTful API which can be used to interact with the service.\n\nUnless otherwise specified, authentication is required for all API calls. You can authenticate using\nbasic authentication with the admin username and password.\n\n## CSRF Protection\n\nState-changing API endpoints (POST, DELETE) are protected against Cross-Site Request Forgery (CSRF) attacks.\n\n**For Web Browsers:**\n- Requests from same-origin (configured via `csrf_allowed_origins`) are automatically allowed\n- Cross-origin requests require a CSRF token\n\n**For Non-Browser Applications:**\n- Non-browser clients (e.g. `curl`, scripts, custom apps) are **exempt** from CSRF protection\n- CSRF attacks require a browser to silently attach credentials to a cross-origin request — this threat\n  does not apply to non-browser clients that explicitly provide credentials with every request\n- Requests with no `Origin` or `Referer` header (as is typical for non-browser clients) are automatically\n  allowed without a CSRF token\n\n**Example (browser-equivalent cross-origin request):**\n```bash\n# Get CSRF token\ncurl -u user:pass https://localhost:47990/api/csrf-token\n\n# Use token in request\ncurl -u user:pass -H \"X-CSRF-Token: your_token_here\" \\\n  -X POST https://localhost:47990/api/restart\n```\n\n@htmlonly\n<script src=\"api.js\"></script>\n@endhtmlonly\n\n## GET /api/csrf-token\n@copydoc confighttp::getCSRFToken()\n\n## GET /api/apps\n@copydoc confighttp::getApps()\n\n## POST /api/apps\n@copydoc confighttp::saveApp()\n\n## POST /api/apps/close\n@copydoc confighttp::closeApp()\n\n## DELETE /api/apps/{index}\n@copydoc confighttp::deleteApp()\n\n## GET /api/browse\n@copydoc confighttp::browseDirectory()\n\n## GET /api/clients/list\n@copydoc confighttp::getClients()\n\n## POST /api/clients/unpair\n@copydoc confighttp::unpair()\n\n## POST /api/clients/unpair-all\n@copydoc confighttp::unpairAll()\n\n## POST /api/clients/update\n@copydoc confighttp::updateClient()\n\n## GET /api/config\n@copydoc confighttp::getConfig()\n\n## GET /api/configLocale\n@copydoc confighttp::getLocale()\n\n## POST /api/config\n@copydoc confighttp::saveConfig()\n\n## GET /api/covers/{index}\n@copydoc confighttp::getCover()\n\n## POST /api/covers/upload\n@copydoc confighttp::uploadCover()\n\n## GET /api/logs\n@copydoc confighttp::getLogs()\n\n## POST /api/password\n@copydoc confighttp::savePassword()\n\n## POST /api/pin\n@copydoc confighttp::savePin()\n\n## POST /api/reset-display-device-persistence\n@copydoc confighttp::resetDisplayDevicePersistence()\n\n## POST /api/reset-portal-token\n@copydoc confighttp::resetPortalToken()\n\n## POST /api/restart\n@copydoc confighttp::restart()\n\n## GET /api/virtual-input/status\n@copydoc confighttp::getVirtualInputStatus()\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/LizardByte/Sunshine/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"## Build and tests\n\nOn Windows we use msys2 and ucrt64 to compile.\nPrefix Windows build and test commands with `C:\\msys64\\msys2_shell.cmd -defterm -here -no-start -ucrt64 -c`.\n\nPrefix build directories with `cmake-build-`.\n\nThe test executable is named `test_sunshine` and will be located inside the `tests` directory within\nthe build directory.\n\nThe project uses gtest as a test framework.\n\nSunshine tests must include `tests/tests_common.h` using the appropriate relative path, rather than including\n`<gtest/gtest.h>` directly. The common header provides GoogleTest through the shared test support and makes\n`TEST` use `BaseTest`, including its output capture and shared setup/teardown.\n\nGroup test headers first under `// test includes`, followed by `// standard includes`, `// lib includes`, and\n`// local includes`, with a blank line between groups. Put shared test helpers in the test group, and omit empty\ngroups. Keep platform-specific headers and their group comments inside the appropriate preprocessor guards.\nWhen a test depends on a particular include order, preserve that order and explain the dependency in a comment;\ndo not move the common header ahead of headers whose first-include behavior is being tested.\n\nAdd or update regression tests for new or modified source-code methods and behavior.\nTarget 100% coverage on changed source code.\n\nThe regression-test requirement does not apply to build-system files, such as CMake scripts and dependency configuration.\nValidate build-system changes with appropriate configuration, build, and lint checks.\nDo not add dedicated build-system regression-test projects or fixtures for these changes.\n\n## Python tooling and formatting\n\nFrom the repository root, run `uv sync --locked` to create or refresh `.venv` from `pyproject.toml` and `uv.lock`.\nRe-run it after switching branches or changing either file or the `third-party/lizardbyte-common` submodule.\nAfter changing dependency declarations or the submodule revision, run `uv lock` before syncing.\n\nAfter native code changes, run `uv run --locked lb-update-clang-format` from the repository root. The command is\nprovided by `third-party/lizardbyte-common`; inspect the resulting diff for unrelated formatting changes.\n\n## Code style and documentation\n\nWhen adding localization do not update any language other than `en`. This also means to exclude en-US or other variants.\n\nAlways add or update doxygen documentation.\n\nThe project requires that everything be documented in doxygen or the build will fail.\n\nPrimary doxygen comments should be done like so:\n\n```cpp\n  /**\n   * @brief Describe the function, structure, etc.\n   *\n   * @param my_param Describe the parameter.\n   * @return Describe the return.\n   */\n```\n\nInline doxygen comments should use `///< ...` instead of `/**< ... */`.\n\nAlways follow the style guidelines defined in .clang-format for c/c++ code.\n\nDo not add decorative separator comments, including dashed banners that label groups of tests. Use descriptive\ntest names and code structure to show the grouping instead.\n\n## Issues and pull requests\n\nWhen asked to create an issue or pull request, use the templates provided by the LizardByte/.github repo or\nLizardByte/Sunshine repo, with the Sunshine templates taking precedence if both exist. At the end of the issue\nor pull request body, add an attribution naming the AI agent, model, and thinking level used to generate it.\nRepeat that attribution in a separate comment on the created issue or pull request. For example:\n\n```\n> This issue was generated by ChatGPT 6 Sol, extra high thinking level\n```\n\nWhen asked to create an issue, do only enough investigation to verify and accurately describe the problem unless the\nuser also asks for an investigation. Keep the issue concise: state the observed behavior, expected behavior, and\nreproduction steps or evidence when available. Do not include an exhaustive root-cause analysis or implementation\nplan in the issue. This limit applies only to creating issues; investigate or fix issues fully when asked.\n\n## Code Review Rules\n\nCheck new and modified tests for the common-header and include-group conventions above. Request\n`tests_common.h` instead of direct GoogleTest includes, and ensure shared test helpers are in the test include\ngroup. Verify any documented include-order dependency before asking the author to reorder headers.\n\nReport concrete issues introduced by the change that the contributor can address. For each finding, explain the\ntriggering condition, impact, and a practical fix; point to the relevant code or test. Keep workflow status separate\nfrom code findings.\n\nIf GitHub Actions workflows are queued for maintainer approval, or a dependent check times out before its job can run,\ndo not leave an inline comment, request changes, or ask the contributor to run the workflows. The maintainer controls\napproval. If the missing results materially limit the review, mention that once in the review summary as a verification\nlimit for the maintainer. Review actual failed checks for change-related problems when their logs are available.\n\nFor pull request reviews, verify the current PR head and mergeability against its target branch. If conflicts are\nconfirmed, tell the author in the review summary that the PR needs to be rebased and the conflicts resolved before\nmerging. Do not infer conflicts from an unknown or pending mergeability status.\n\nWhen approving a pull request, the approval itself is sufficient. Do not add a comment solely to accompany it.\n","isInternal":false,"tokens":1115,"sizeBytes":5508},{"name":"api.md","path":"docs/api.md","rawUrl":"https://raw.githubusercontent.com/LizardByte/Sunshine/HEAD/docs/api.md","title":"docs - API Interface Contract & Specifications","category":"project-spec","format":"markdown","content":"# API\n\nSunshine has a RESTful API which can be used to interact with the service.\n\nUnless otherwise specified, authentication is required for all API calls. You can authenticate using\nbasic authentication with the admin username and password.\n\n## CSRF Protection\n\nState-changing API endpoints (POST, DELETE) are protected against Cross-Site Request Forgery (CSRF) attacks.\n\n**For Web Browsers:**\n- Requests from same-origin (configured via `csrf_allowed_origins`) are automatically allowed\n- Cross-origin requests require a CSRF token\n\n**For Non-Browser Applications:**\n- Non-browser clients (e.g. `curl`, scripts, custom apps) are **exempt** from CSRF protection\n- CSRF attacks require a browser to silently attach credentials to a cross-origin request — this threat\n  does not apply to non-browser clients that explicitly provide credentials with every request\n- Requests with no `Origin` or `Referer` header (as is typical for non-browser clients) are automatically\n  allowed without a CSRF token\n\n**Example (browser-equivalent cross-origin request):**\n```bash\n# Get CSRF token\ncurl -u user:pass https://localhost:47990/api/csrf-token\n\n# Use token in request\ncurl -u user:pass -H \"X-CSRF-Token: your_token_here\" \\\n  -X POST https://localhost:47990/api/restart\n```\n\n@htmlonly\n<script src=\"api.js\"></script>\n@endhtmlonly\n\n## GET /api/csrf-token\n@copydoc confighttp::getCSRFToken()\n\n## GET /api/apps\n@copydoc confighttp::getApps()\n\n## POST /api/apps\n@copydoc confighttp::saveApp()\n\n## POST /api/apps/close\n@copydoc confighttp::closeApp()\n\n## DELETE /api/apps/{index}\n@copydoc confighttp::deleteApp()\n\n## GET /api/browse\n@copydoc confighttp::browseDirectory()\n\n## GET /api/clients/list\n@copydoc confighttp::getClients()\n\n## POST /api/clients/unpair\n@copydoc confighttp::unpair()\n\n## POST /api/clients/unpair-all\n@copydoc confighttp::unpairAll()\n\n## POST /api/clients/update\n@copydoc confighttp::updateClient()\n\n## GET /api/config\n@copydoc confighttp::getConfig()\n\n## GET /api/configLocale\n@copydoc confighttp::getLocale()\n\n## POST /api/config\n@copydoc confighttp::saveConfig()\n\n## GET /api/covers/{index}\n@copydoc confighttp::getCover()\n\n## POST /api/covers/upload\n@copydoc confighttp::uploadCover()\n\n## GET /api/logs\n@copydoc confighttp::getLogs()\n\n## POST /api/password\n@copydoc confighttp::savePassword()\n\n## POST /api/pin\n@copydoc confighttp::savePin()\n\n## POST /api/reset-display-device-persistence\n@copydoc confighttp::resetDisplayDevicePersistence()\n\n## POST /api/reset-portal-token\n@copydoc confighttp::resetPortalToken()\n\n## POST /api/restart\n@copydoc confighttp::restart()\n\n## GET /api/virtual-input/status\n@copydoc confighttp::getVirtualInputStatus()\n","isInternal":false,"tokens":692,"sizeBytes":2663}],"systemPromptSnippet":"<yakaai_skills repo=\"LizardByte/Sunshine\">\n<!-- File: AGENTS.md (Tokens: ~1115 | Category: root-instruction) -->\n## Build and tests\n\nOn Windows we use msys2 and ucrt64 to compile.\nPrefix Windows build and test commands with `C:\\msys64\\msys2_shell.cmd -defterm -here -no-start -ucrt64 -c`.\n\nPrefix build directories with `cmake-build-`.\n\nThe test executable is named `test_sunshine` and will be located inside the `tests` directory within\nthe build directory.\n\nThe project uses gtest as a test framework.\n\nSunshine tests must include `tests/tests_common.h` using the appropriate relative path, rather than including\n`<gtest/gtest.h>` directly. The common header provides GoogleTest through the shared test support and makes\n`TEST` use `BaseTest`, including its output capture and shared setup/teardown.\n\nGroup test headers first under `// test includes`, followed by `// standard includes`, `// lib includes`, and\n`// local includes`, with a blank line between groups. Put shared test helpers in the test group, and omit empty\ngroups. Keep platform-specific headers and their group comments inside the appropriate preprocessor guards.\nWhen a test depends on a particular include order, preserve that order and explain the dependency in a comment;\ndo not move the common header ahead of headers whose first-include behavior is being tested.\n\nAdd or update regression tests for new or modified source-code methods and behavior.\nTarget 100% coverage on changed source code.\n\nThe regression-test requirement does not apply to build-system files, such as CMake scripts and dependency configuration.\nValidate build-system changes with appropriate configuration, build, and lint checks.\nDo not add dedicated build-system regression-test projects or fixtures for these changes.\n\n## Python tooling and formatting\n\nFrom the repository root, run `uv sync --locked` to create or refresh `.venv` from `pyproject.toml` and `uv.lock`.\nRe-run it after switching branches or changing either file or the `third-party/lizardbyte-common` submodule.\nAfter changing dependency declarations or the submodule revision, run `uv lock` before syncing.\n\nAfter native code changes, run `uv run --locked lb-update-clang-format` from the repository root. The command is\nprovided by `third-party/lizardbyte-common`; inspect the resulting diff for unrelated formatting changes.\n\n## Code style and documentation\n\nWhen adding localization do not update any language other than `en`. This also means to exclude en-US or other variants.\n\nAlways add or update doxygen documentation.\n\nThe project requires that everything be documented in doxygen or the build will fail.\n\nPrimary doxygen comments should be done like so:\n\n```cpp\n  /**\n   * @brief Describe the function, structure, etc.\n   *\n   * @param my_param Describe the parameter.\n   * @return Describe the return.\n   */\n```\n\nInline doxygen comments should use `///< ...` instead of `/**< ... */`.\n\nAlways follow the style guidelines defined in .clang-format for c/c++ code.\n\nDo not add decorative separator comments, including dashed banners that label groups of tests. Use descriptive\ntest names and code structure to show the grouping instead.\n\n## Issues and pull requests\n\nWhen asked to create an issue or pull request, use the templates provided by the LizardByte/.github repo or\nLizardByte/Sunshine repo, with the Sunshine templates taking precedence if both exist. At the end of the issue\nor pull request body, add an attribution naming the AI agent, model, and thinking level used to generate it.\nRepeat that attribution in a separate comment on the created issue or pull request. For example:\n\n```\n> This issue was generated by ChatGPT 6 Sol, extra high thinking level\n```\n\nWhen asked to create an issue, do only enough investigation to verify and accurately describe the problem unless the\nuser also asks for an investigation. Keep the issue concise: state the observed behavior, expected behavior, and\nreproduction steps or evidence when available. Do not include an exhaustive root-cause analysis or implementation\nplan in the issue. This limit applies only to creating issues; investigate or fix issues fully when asked.\n\n## Code Review Rules\n\nCheck new and modified tests for the common-header and include-group conventions above. Request\n`tests_common.h` instead of direct GoogleTest includes, and ensure shared test helpers are in the test include\ngroup. Verify any documented include-order dependency before asking the author to reorder headers.\n\nReport concrete issues introduced by the change that the contributor can address. For each finding, explain the\ntriggering condition, impact, and a practical fix; point to the relevant code or test. Keep workflow status separate\nfrom code findings.\n\nIf GitHub Actions workflows are queued for maintainer approval, or a dependent check times out before its job can run,\ndo not leave an inline comment, request changes, or ask the contributor to run the workflows. The maintainer controls\napproval. If the missing results materially limit the review, mention that once in the review summary as a verification\nlimit for the maintainer. Review actual failed checks for change-related problems when their logs are available.\n\nFor pull request reviews, verify the current PR head and mergeability against its target branch. If conflicts are\nconfirmed, tell the author in the review summary that the PR needs to be rebased and the conflicts resolved before\nmerging. Do not infer conflicts from an unknown or pending mergeability status.\n\nWhen approving a pull request, the approval itself is sufficient. Do not add a comment solely to accompany it.\n\n<!-- File: docs/api.md (Tokens: ~692 | Category: project-spec) -->\n# API\n\nSunshine has a RESTful API which can be used to interact with the service.\n\nUnless otherwise specified, authentication is required for all API calls. You can authenticate using\nbasic authentication with the admin username and password.\n\n## CSRF Protection\n\nState-changing API endpoints (POST, DELETE) are protected against Cross-Site Request Forgery (CSRF) attacks.\n\n**For Web Browsers:**\n- Requests from same-origin (configured via `csrf_allowed_origins`) are automatically allowed\n- Cross-origin requests require a CSRF token\n\n**For Non-Browser Applications:**\n- Non-browser clients (e.g. `curl`, scripts, custom apps) are **exempt** from CSRF protection\n- CSRF attacks require a browser to silently attach credentials to a cross-origin request — this threat\n  does not apply to non-browser clients that explicitly provide credentials with every request\n- Requests with no `Origin` or `Referer` header (as is typical for non-browser clients) are automatically\n  allowed without a CSRF token\n\n**Example (browser-equivalent cross-origin request):**\n```bash\n# Get CSRF token\ncurl -u user:pass https://localhost:47990/api/csrf-token\n\n# Use token in request\ncurl -u user:pass -H \"X-CSRF-Token: your_token_here\" \\\n  -X POST https://localhost:47990/api/restart\n```\n\n@htmlonly\n<script src=\"api.js\"></script>\n@endhtmlonly\n\n## GET /api/csrf-token\n@copydoc confighttp::getCSRFToken()\n\n## GET /api/apps\n@copydoc confighttp::getApps()\n\n## POST /api/apps\n@copydoc confighttp::saveApp()\n\n## POST /api/apps/close\n@copydoc confighttp::closeApp()\n\n## DELETE /api/apps/{index}\n@copydoc confighttp::deleteApp()\n\n## GET /api/browse\n@copydoc confighttp::browseDirectory()\n\n## GET /api/clients/list\n@copydoc confighttp::getClients()\n\n## POST /api/clients/unpair\n@copydoc confighttp::unpair()\n\n## POST /api/clients/unpair-all\n@copydoc confighttp::unpairAll()\n\n## POST /api/clients/update\n@copydoc confighttp::updateClient()\n\n## GET /api/config\n@copydoc confighttp::getConfig()\n\n## GET /api/configLocale\n@copydoc confighttp::getLocale()\n\n## POST /api/config\n@copydoc confighttp::saveConfig()\n\n## GET /api/covers/{index}\n@copydoc confighttp::getCover()\n\n## POST /api/covers/upload\n@copydoc confighttp::uploadCover()\n\n## GET /api/logs\n@copydoc confighttp::getLogs()\n\n## POST /api/password\n@copydoc confighttp::savePassword()\n\n## POST /api/pin\n@copydoc confighttp::savePin()\n\n## POST /api/reset-display-device-persistence\n@copydoc confighttp::resetDisplayDevicePersistence()\n\n## POST /api/reset-portal-token\n@copydoc confighttp::resetPortalToken()\n\n## POST /api/restart\n@copydoc confighttp::restart()\n\n## GET /api/virtual-input/status\n@copydoc confighttp::getVirtualInputStatus()\n</yakaai_skills>"}