# Фреймворк приложений DFWebOS

Если вы умеете писать код на любом языке, значит, вы уже знаете, как разрабатывать приложение для DFWebOS. Ограничений по языкам программирования, фреймворкам или базам данных нет. Приложения работают внутри изолированных контейнеров [Docker](https://docs.docker.com/), и единственное требование заключается в том, что они должны предоставлять веб-интерфейс.

> Некоторые серверные приложения могут вообще не иметь UI. В таком случае приложение должно отдавать простую веб-страницу со сведениями для подключения, QR-кодами, инструкциями по настройке и всем остальным, что нужно пользователю для подключения. Предполагается, что у пользователя никогда не будет доступа к CLI в DFWebOS.

Чтобы документ оставался коротким и понятным, мы не будем углубляться в сам процесс разработки приложения, а сосредоточимся на упаковке и тестировании уже существующего приложения.

Давайте сразу перейдем к делу и упакуем [BTC RPC Explorer](https://github.com/janoside/btc-rpc-explorer) - приложение на Node.js - для DFWebOS.

Это делается в 4 шага:

1. [🛳 Контейнеризация приложения с помощью Docker](#1-контейнеризация-приложения-с-помощью-docker)
1. [☂️ Упаковка приложения для DFWebOS](#2-️упаковка-приложения-для-dfwebos)
1. [🛠 Тестирование приложения в DFWebOS](#3-тестирование-приложения-в-dfwebos)
  1. [Тестирование в среде разработки DFWebOS на локальной машине](#31-тестирование-в-среде-разработки-dfwebos-на-локальной-машине)
  1. [Тестирование в DFWebOS, запущенной на физическом устройстве](#32-тестирование-в-dfwebos-запущенной-на-физическом-устройстве)
1. [🚀 Отправка приложения](#4-отправка-приложения)
___

## 1. 🛳&nbsp;&nbsp;Контейнеризация приложения с помощью Docker

1\. Начнем с клонирования BTC RPC Explorer на нашу систему:

```sh
git clone --branch v2.0.2 https://github.com/janoside/btc-rpc-explorer.git
cd  btc-rpc-explorer
```

2\. Далее создадим `Dockerfile` в каталоге приложения:

```Dockerfile
FROM node:12-buster-slim AS builder

WORKDIR /build
COPY . .
RUN apt-get update
RUN apt-get install -y git python3 build-essential
RUN npm ci --production

FROM node:12-buster-slim

USER 1000
WORKDIR /build
COPY --from=builder /build .
EXPOSE 3002
CMD ["npm", "start"]
```

### Хороший Dockerfile:

- [x] Использует легковесный базовый образ, что уменьшает потребление места и ускоряет установку приложения.
- [x] Использует [многоэтапные сборки](https://docs.docker.com/develop/develop-images/multistage-build/) для уменьшения размера образа.
- [x] Исключает файлы разработки из итогового образа.
- [x] Содержит только один сервис на контейнер.
- [x] Не запускает сервис от имени root.
- [x] Использует удаленные ресурсы, проверяемые по контрольной сумме.
- [x] Обеспечивает детерминированные сборки образов.

3\. Теперь мы готовы собрать Docker-образ BTC RPC Explorer. DFWebOS поддерживает как 64-битные ARM-, так и x86-архитектуры, поэтому мы будем использовать `docker buildx`, чтобы собрать, промаркировать и отправить мультиархитектурные Docker-образы нашего приложения в Docker Hub. Так одно и то же приложение можно устанавливать как на ARM-, так и на x86-устройства.

```sh
docker buildx build --platform linux/arm64,linux/amd64 --tag getwebos/btc-rpc-explorer:v2.0.2 --output "type=registry" .
```

> Чтобы использовать `docker buildx`, необходимо включить ["experimental features"](https://docs.docker.com/engine/reference/commandline/cli/#experimental-features) в Docker.

___

## 2. ☂️&nbsp;&nbsp;Упаковка приложения для DFWebOS

1\. Сначала сделаем fork репозитория [getwebos/dfwebos-apps](https://github.com/getwebos/dfwebos-apps) на GitHub, клонируем наш fork локально, создадим новую ветку для приложения и переключимся на нее:

```sh
git clone https://github.com/<YOUR-GITHUB-USERNAME>/dfwebos-apps.git
cd dfwebos-apps
```

2\. Теперь нужно выбрать ID для приложения. ID приложения должен содержать только строчные латинские буквы и дефисы, а также быть читаемым и узнаваемым. Для этого приложения мы используем `btc-rpc-explorer`.

Нужно создать новый подкаталог в директории `apps` с тем же именем, что и ID нашего приложения, и перейти в него:

```sh
mkdir btc-rpc-explorer
cd btc-rpc-explorer
```

3\. Внутри директории приложения создадим каркас со следующими файлами:

- `docker-compose.yml` - используется для запуска и остановки Docker-контейнеров вашего приложения
- `dfwebos-app.yml` - файл манифеста приложения, чтобы DFWebOS знал имя и версию приложения
- `exports.sh` - shell-скрипт для экспорта переменных окружения, используемых в `docker-compose.yml`, и для передачи их другим установленным приложениям

Теперь создадим в этой директории файл `docker-compose.yml`, чтобы описать наше приложение.

> Не знакомы с Docker Compose? Это простой инструмент для описания и запуска Docker-приложений, которые могут состоять из нескольких контейнеров. Следуйте этому руководству: если вы уже понимаете основы Docker, все будет несложно.

Скопируйте следующий шаблон `docker-compose.yml` в текстовый редактор и измените его под ваше приложение.

```yml
version: "3.7"

services:
  app_proxy:
    environment:
      # <app-id>_<web-container-name>_1
      # например, 'btc-rpc-explorer_web_1'
      # Обратите внимание, что суффикс '_1' в конце обязателен
      APP_HOST: <web-container-dns-name>
      APP_PORT: <web-container-port-number>
  
  web:
    image: <docker-image>:<tag>@sha256:<digest>
    restart: on-failure
    stop_grace_period: 1m
    ports:
      # Не нужно публиковать порт, который слушает веб-сервер вашего приложения,
      # если вы используете сервис app_proxy.
      # Это обрабатывается переменными окружения APP_HOST и APP_PORT в сервисе выше.
      #
      # Если нужно открыть дополнительные порты, можно сделать это так,
      # заменив <port> на нужный номер порта:
      - <port>:<port>
    volumes:
      # Раскомментируйте, чтобы смонтировать каталоги данных внутрь
      # Docker-контейнера для хранения постоянных данных
      # - ${APP_DATA_DIR}/foo:/foo
      # - ${APP_DATA_DIR}/bar:/bar
      #
      # Раскомментируйте, чтобы смонтировать каталог данных LND только для чтения
      # внутрь Docker-контейнера по пути /lnd
      # - ${APP_LIGHTNING_NODE_DATA_DIR}:/lnd:ro
      #
      # Раскомментируйте, чтобы смонтировать каталог данных Bitcoin Core
      # только для чтения внутрь Docker-контейнера по пути /bitcoin
      # - ${APP_BITCOIN_DATA_DIR}:/bitcoin:ro
    environment:
      # Передавайте любые переменные окружения в приложение для конфигурации в виде:
      # VARIABLE_NAME: value
      #
      # Ниже перечислены все переменные, которые DFWebOS предоставляет и которые можно
      # передать в приложение
      # Переменные окружения уровня системы
      # $DEVICE_HOSTNAME - hostname устройства с сервером DFWebOS (например, "webos")
      # $DEVICE_DOMAIN_NAME - доменное имя .local для сервера DFWebOS (например, "webos.local")
      #
      # Переменные окружения Tor-прокси
      # $TOR_PROXY_IP - локальный IP Tor-прокси
      # $TOR_PROXY_PORT - порт Tor-прокси
      #
      # Переменные окружения, относящиеся к приложению
      # $APP_HIDDEN_SERVICE - адрес Tor hidden service, по которому будет доступно ваше приложение
      # $APP_PASSWORD - уникальный пароль в открытом виде, который можно использовать для аутентификации в приложении; он показывается пользователю в UI DFWebOS
      # $APP_SEED - уникальная 256-битная hex-строка (128 бит энтропии), детерминированно полученная из seed пользователя DFWebOS и ID вашего приложения
  # Если у приложения есть дополнительные сервисы, например контейнер базы данных,
  # их можно определить ниже:
  # db:
  #   image: <docker-image>:<tag>@sha256:<digest>
  #   ...

```

YAML-файл манифеста приложения сообщает DFWebOS сведения о приложении, такие как имя, описание, зависимости, порт для доступа к приложению и т.д.

> Сейчас существуют две версии манифеста: `1` и `1.1`. Версия `1` является базовой и подходит для большинства приложений. Однако если приложению нужны hooks (скрипты, которые запускаются на разных этапах жизненного цикла приложения), необходимо использовать версию `1.1`. Hooks позволяют выполнять пользовательские действия на разных стадиях жизненного цикла приложения, например перед запуском (pre-start), после установки (post-install) и т.д. Если hooks не нужны, достаточно версии манифеста `1`.

```yml
manifestVersion: 1
id: btc-rpc-explorer
category: finance
name: BTC RPC Explorer
version: "3.3.0"
tagline: Simple, database-free blockchain explorer
description: >-
  BTC RPC Explorer is a full-featured, self-hosted explorer for the
  Bitcoin blockchain. With this explorer, you can explore not just the
  blockchain database, but also explore the functional capabilities of your
  DFWebOS.

  It comes with a network summary dashboard, detailed view of blocks, transactions, addresses, along with analysis tools for viewing stats on miner activity, mempool summary, with fee, size, and age breakdowns. You can also search by transaction ID, block hash/height, and addresses.

  It's time to appreciate the "fullness" of your node.
releaseNotes: >-
  Dark mode is finally here! Easily switch between your preferred mode
  in one click.

  This version also includes lots of minor styling improvements, better
  error handling, and several bugfixes.
developer: Dan Janosik
website: https://explorer.btc21.org
dependencies:
  - bitcoin
  - electrs
repo: https://github.com/janoside/btc-rpc-explorer
support: https://github.com/janoside/btc-rpc-explorer/discussions
port: 3002
gallery:
  - 1.jpg
  - 2.jpg
  - 3.jpg
path: ""
defaultUsername: ""
defaultPassword: ""
submitter: DFWebOS
submission: https://github.com/getwebos/dfwebos/pull/334
```

При отправке нового приложения оставьте поля `gallery` и `releaseNotes` пустыми. Используйте следующие значения:

```yml
gallery: []
releaseNotes: ""
```

Раздел `dependencies` в манифесте приложения сообщает DFWebOS список ID приложений, которые должны быть уже установлены, чтобы пользователь мог установить BTC RPC Explorer и чтобы оно корректно работало.

Shell-скрипт `exports.sh` - это простой скрипт для экспорта переменных окружения, которые может читать ваш `docker-compose.yml`. Эти переменные окружения также становятся доступными другим приложениям при запуске через их файлы `docker-compose.yml`. Большинству приложений эта возможность не потребуется.

Если бы мы, например, хотели предоставить другим приложениям доступ к Address API BTC RPC Explorer, это выглядело бы так:
```sh
export APP_BTC_RPC_EXPLORER_ADDRESS_API="electrumx"
```

4\. Для нашего приложения мы заменим `<docker-image>` на `getwebos/btc-rpc-explorer`, `<tag>` на `v2.0.2`, `<digest>` на `f8ba8b97e550f65e5bc935d7516cce7172910e9009f3154a434c7baf55e82a2b`, а `<port>` на `3002`. Поскольку BTC RPC Explorer не нужно хранить постоянные данные и ему не требуется доступ к каталогам данных Bitcoin Core или LND, мы можем удалить весь блок `volumes`.

> Digest - это уникальный неизменяемый идентификатор Docker-образа. В файле `docker-compose.yml` он имеет приоритет над tag. Мы хотим подтягивать образ по digest, потому что так гарантированно получаем в точности один и тот же образ при каждом запуске, и именно этот образ был протестирован и подтвержден как рабочий в DFWebOS. Важно убедиться, что это мультиархитектурный digest, а не digest для конкретной архитектуры.

BTC RPC Explorer - это приложение с одним Docker-контейнером, поэтому нам не нужно определять дополнительные сервисы (например, сервис базы данных) в compose-файле.

> Если бы BTC RPC Explorer нужно было сохранять какие-то данные, мы бы создали новый каталог `data` рядом с `docker-compose.yml`. Затем мы бы смонтировали том `- ${APP_DATA_DIR}/data:/data` в `docker-compose.yml`, чтобы этот каталог был доступен в контейнере по пути `/data`.

Обновленный файл `docker-compose.yml`:

```yml
version: "3.7"

services:
  app_proxy:
    environment:
      APP_HOST: btc-rpc-explorer_web_1
      APP_PORT: 8080

  web:
    image: getwebos/btc-rpc-explorer:v2.0.2@sha256:f8ba8b97e550f65e5bc935d7516cce7172910e9009f3154a434c7baf55e82a2b
    restart: on-failure
    stop_grace_period: 1m
    environment:
      BTCEXP_PORT: 8080

```

5\. Далее зададим переменные окружения, необходимые приложению для подключения к Bitcoin Core, Electrum server и для конфигурации самого приложения ([как того требует приложение](https://github.com/janoside/btc-rpc-explorer/blob/master/.env-sample)).

Итоговая версия `docker-compose.yml` будет такой:

```yml
version: "3.7"

services:
  app_proxy:
    environment:
      APP_HOST: btc-rpc-explorer_web_1
      APP_PORT: 8080
      
  web:
    image: getwebos/btc-rpc-explorer:v2.0.2
    restart: on-failure
    stop_grace_period: 1m
    environment:
      PORT: 8080

      # Данные для подключения к Bitcoin Core
      BTCEXP_BITCOIND_HOST: $APP_BITCOIN_NODE_IP
      BTCEXP_BITCOIND_PORT: $APP_BITCOIN_RPC_PORT
      BTCEXP_BITCOIND_USER: $APP_BITCOIN_RPC_USER
      BTCEXP_BITCOIND_PASS: $APP_BITCOIN_RPC_PASS

      # Данные для подключения к Electrum
      BTCEXP_ELECTRUMX_SERVERS: "tcp://$APP_ELECTRS_NODE_IP:$APP_ELECTRS_NODE_PORT"

      # Конфигурация приложения
      BTCEXP_HOST: 0.0.0.0
      DEBUG: "btcexp:*,electrumClient"
      BTCEXP_ADDRESS_API: electrumx
      BTCEXP_SLOW_DEVICE_MODE: "true"
      BTCEXP_NO_INMEMORY_RPC_CACHE: "true"
      BTCEXP_PRIVACY_MODE: "true"
      BTCEXP_NO_RATES: "true"
      BTCEXP_RPC_ALLOWALL: "false"
      BTCEXP_BASIC_AUTH_PASSWORD: ""  

```

6\. Здесь мы почти закончили. Следующий шаг - закоммитить изменения, отправить их в ветку нашего fork и протестировать приложение в DFWebOS.

```sh
git add .
git commit -m "Add BTC RPC Explorer"
git push
```

___

## 3. 🛠&nbsp;&nbsp;Тестирование приложения в DFWebOS

🚨 Это текущий процесс тестирования приложения в DFWebOS 1.x. Фреймворк приложений находится в активной разработке, и этот процесс в будущем изменится. Для тестирования в DFWebOS 0.5.4 обратитесь к [предыдущей версии этого документа](https://github.com/getwebos/dfwebos-apps/blob/9eae789b8512ef2a213805524e17f33d2128e33e/README.md).

### 3.1 Тестирование в среде разработки DFWebOS на локальной машине

Среда разработки DFWebOS (dfwebos-dev) требует Docker-окружение, которое предоставляет IP-адреса контейнеров хосту. Именно так Docker работает нативно в Linux, а в macOS этого можно добиться с помощью OrbStack, а в Windows - с помощью WSL 2.

1\. Установите [OrbStack](https://orbstack.dev/) на macOS или [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/install) вместе с Docker Desktop на Windows.

2\. Клонируйте репозиторий [getwebos/dfwebos](https://github.com/getwebos/dfwebos).

Из корня клонированного репозитория выполните следующую команду, чтобы посмотреть доступные команды dfwebos-dev:

```sh
npm run dev help
```

Чтобы запустить среду разработки, выполните команду:

```sh
npm run dev
```

> [!NOTE]
> Если вы запускаете среду разработки впервые, локальная сборка образа ОС может занять некоторое время.

После инициализации DFWebOS будет доступна по адресу http://dfwebos-dev.local.

3\. Скопируйте каталог приложения (исключая файлы `.gitkeep`) в каталог app-store в dfwebos-dev.

Для этого на локальной машине выполните:

```sh
rsync -av --exclude=".gitkeep" <path-to-your-forked-repo-on-local-machine>/btc-rpc-explorer dfwebos@dfv24-dev.local:/home/webos/dfwebos/app-stores/getwebos-dfwebos-apps-github-53f74447/
```

Если во время передачи будет запрошен пароль, используйте пароль, который вы задали при создании учетной записи DFWebOS.

4\. Установите приложение.

На домашнем экране DFWebOS откройте App Store, найдите BTC RPC Explorer, нажмите кнопку "Install" и дождитесь завершения установки.

Приложение также можно установить из командной строки. DFWebOS предоставляет веб-терминал, доступный через Settings > Advanced Settings > Terminal > DFWebOS, либо можно использовать скрипты dfwebos-dev для установки приложения через сервер RPC dfwebosd:

```sh
npm run dev client -- apps.install.mutate -- --appId btc-rpc-explorer
```

Вот и все. Теперь наше приложение BTC RPC Explorer должно быть доступно по адресу http://dfwebos-dev.local:3002

Чтобы удалить приложение, можно щелкнуть правой кнопкой мыши по его значку на домашнем экране и выбрать "Uninstall". Также удалить приложение можно с помощью скриптов dfwebos-dev:

```sh
npm run dev client -- apps.uninstall.mutate -- --appId btc-rpc-explorer
```

> [!WARNING]
> При тестировании приложения обязательно проверьте, что все состояние приложения, которое должно сохраняться, действительно сохраняется в томах.
>
> Хороший способ это проверить - перезапустить приложение (щелкните правой кнопкой мыши по значку приложения на домашнем экране и выберите "Restart"). Если какие-то данные теряются, значит их нужно привязать к постоянному тому.
>
> При остановке и последующем запуске приложения все данные в томах сохраняются, а все остальное отбрасывается. При удалении и повторной установке приложения удаляются даже постоянные данные.

### 3.2 Тестирование в DFWebOS, запущенной на физическом устройстве

Запустить DFWebOS можно несколькими способами:
  
1. [Установить DFWebOS на Raspberry Pi 5](https://github.com/getwebos/dfwebos/wiki/Install-DFWebOS-on-a-Raspberry-Pi-5)
2. [Установить DFWebOS на любую x86-систему](https://github.com/getwebos/dfwebos/wiki/Install-DFWebOS-on-x86-Systems)
3. [Установить DFWebOS в виртуальную машину](https://github.com/getwebos/dfwebos/wiki/Install-DFWebOS-on-a-Linux-VM)
4. [Приобрести DFWebOS Home](https://dfwebos.com/dfwebos-home)

Независимо от выбранного способа, после того как DFWebOS будет запущена и вы откроете http://dfwebos.local и создадите учетную запись, можно выполнить следующие шаги для тестирования приложения.

1\. Скопируйте каталог приложения (исключая файлы `.gitkeep`) в каталог app-store на вашем устройстве с DFWebOS.

Для этого на локальной машине выполните:

```sh
rsync -av --exclude=".gitkeep" <path-to-your-forked-repo-on-local-machine>/btc-rpc-explorer dfwebos@dfwebos.local:/home/dfwebos/dfwebos/app-stores/getwebos-dfwebos-apps-github-53f74447/
```

Если во время передачи будет запрошен пароль, используйте пароль, который вы задали для устройства с DFWebOS при создании учетной записи.

2\. Установите приложение на устройство с DFWebOS:

На домашнем экране DFWebOS откройте App Store, найдите BTC RPC Explorer, нажмите кнопку "Install" и дождитесь завершения установки.

Приложение также можно установить из командной строки. DFWebOS предоставляет веб-терминал, доступный через Settings > Advanced Settings > Terminal > DFWebOS, либо можно подключиться к устройству по SSH с локальной машины через `ssh dfwebos@dfwebos.local`, используя тот же пароль, который вы задали для устройства с DFWebOS при создании учетной записи.

```sh
dfwebosd client apps.install.mutate --appId btc-rpc-explorer
```

Вот и все. Теперь приложение должно быть доступно по адресу http://dfwebos.local:3002

Чтобы удалить приложение, можно щелкнуть правой кнопкой мыши по его значку на домашнем экране и выбрать "Uninstall". Также удалить приложение из командной строки можно так:

```sh
dfwebosd client apps.uninstall.mutate --appId btc-rpc-explorer
```

> [!WARNING]
> При тестировании приложения обязательно проверьте, что все состояние приложения, которое должно сохраняться, действительно сохраняется в томах.
>
> Хороший способ это проверить - перезапустить приложение (щелкните правой кнопкой мыши по значку приложения на домашнем экране и выберите "Restart"). Если какие-то данные теряются, значит их нужно привязать к постоянному тому.
>
> При остановке и последующем запуске приложения все данные в томах сохраняются, а все остальное отбрасывается. При удалении и повторной установке приложения удаляются даже постоянные данные.

___

## 4. 🚀&nbsp;&nbsp;Отправка приложения

Теперь мы готовы открыть pull request в основном репозитории приложений [getwebos/dfwebos-apps](https://github.com/getwebos/dfwebos-apps), чтобы отправить наше приложение. Скопируйте следующий Markdown для описания pull request, заполните его нужными деталями и откройте pull request.

```
# App Submission

### App name
...

### 256x256 SVG icon
_(Upload an icon with no rounded corners as it will be dynamically rounded with CSS.)_
_We will help finalize this icon before the app goes live in the DFWebOS App Store._

...

### Gallery images
_(Upload 3 to 5 high-quality gallery images (1440x900px) of your app in PNG format, or just upload 3 to 5 screenshots of your app and we'll help you design the gallery images.)_
_We will help finalize these images before the app goes live in the DFWebOS App Store._
...


### I have tested my app on:
- [ ] DFWebOS on a Raspberry Pi
- [ ] DFWebOS on a DFWebOS Home
- [ ] DFWebOS on Linux VM
```

Вот где указанная выше информация используется, когда приложение становится доступно в DFWebOS App Store:

<img width="877" alt="image" src="https://github.com/getwebos/dfwebos-apps/assets/85373263/2297030f-909a-4e33-afac-398e30fc79c4">

> После отправки приложения мы проверим ваш pull request, внесем некоторые корректировки в `docker-compose.yml`, например уберем конфликты портов с другими приложениями, закрепим Docker-образы по их sha256 digest, назначим контейнерам уникальные IP-адреса и т.д., а затем выполним merge.

🎉 Поздравляем! Это все, что нужно сделать, чтобы упаковать, протестировать и отправить приложение в DFWebOS. Будем рады видеть вас среди авторов.

---

## Расширенная конфигурация

### App Proxy
DFWebOS App Proxy автоматически защищает приложение, требуя от пользователя ввести пароль DFWebOS либо при входе в основной Web UI, либо при прямом переходе в приложение, например по адресу `http://dfwebos.local:3002`

##### Отключение
В некоторых случаях может понадобиться отключить эту аутентификацию. Это можно сделать, добавив следующую переменную окружения в сервис `app_proxy` Docker Compose:
```
PROXY_AUTH_ADD: "false"
```

##### Белый список / черный список
Некоторые приложения размещают пользовательский UI в корне веб-приложения, а API, например, по пути `/api`. В таком случае желательно, чтобы `/` был защищен DFWebOS, а `/api` - встроенной системой токенов самого приложения. Этого можно добиться, добавив следующую переменную окружения в сервис `app_proxy` Docker Compose:
```
PROXY_AUTH_WHITELIST: "/api/*"
```

Другой пример: корень веб-приложения (`/`) должен быть общедоступным, а административный раздел - защищен DFWebOS. Это можно сделать, добавив следующие переменные окружения в сервис `app_proxy` Docker Compose:
```
PROXY_AUTH_WHITELIST: "*"
PROXY_AUTH_BLACKLIST: "/admin/*"
```

---

## FAQ

1. **Как отправлять обновления приложения?**

    Каждый раз, когда вы выпускаете новую версию приложения, нужно собрать, промаркировать и отправить новые Docker-образы в Docker Hub. Затем откройте новый PR в наш основной репозиторий приложений (getwebos/dfwebos-apps), указав актуальный Docker-образ, а также обновленные поля `version` и `releaseNotes` в файле `dfwebos-app.yml` вашего приложения.

1. **Мне нужна помощь с чем-то еще**

    Можете создать [issue](https://github.com/getwebos/dfwebos-apps/issues) в этом GitHub-репозитории.
