Files
Marat Kharitonov 680104024d
dockerbuild / main (backend, true, backend) (push) Failing after 26m50s
dockerbuild / main (frontend, true, frontend) (push) Failing after 26m57s
dockerbuild / main (worker, true, functions/onprem/worker) (push) Failing after 26m53s
dockerbuild / sync-orborus (push) Failing after 8m45s
docs: document patched backend image + enterprise subscription patch
- CRACKED.md: target image is marker689/shuffle-backend-unchained:12082026
- docker-compose.yml: point backend at patched image (drop override file)
- shared.go: HandleCheckLicense also sets org.Subscriptions to an active
  Enterprise License so the UI shows 'Licensed' (was showing Unlicensed)
- gitignore shuffle-database runtime *.conf

Verified: backend image builds and runs with all limits lifted.
2026-08-12 04:40:47 +03:00

201 lines
9.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Shuffle Cracked — отключение лицензионных ограничений
Этот форк Shuffle содержит патч, который **полностью убирает проверку лицензии** для self-hosted
развёртывания. Ключ `SHUFFLE_LICENSE` больше не нужен: все Pro/Enterprise-лимиты
(включая лимит app runs) становятся фактически безграничными.
Патч протестирован — образ бэкенда успешно собирается в Docker.
---
## Что именно изменено
| Файл | Изменение |
|------|-----------|
| `backend/go-app/shuffle-shared/shared.go` | Три блока `LICENSE BYPASS PATCH` в `HandleCheckLicense` и `IsLicensed`: (1) `HandleCheckLicense` принудительно `org.Licensed = true` + всем `SyncFeatures[*].Active = true, Limit = 1e9` с ранним возвратом; (2) `IsLicensed` возвращает `true`. |
| `backend/go-app/shuffle-shared/db-connector.go` | Блок `LICENSE BYPASS PATCH` в `checkNoInternet()`: всегда возвращает `Valid=true` и лимиты `1e9`. Это закрывает прямые чтения в `SetWorkflowQueue` (app runs) и проверке суб-организаций. |
| `backend/go-app/go.mod` | Включён `replace github.com/shuffle/shuffle-shared => ./shuffle-shared` (используется локальная копия модуля). |
| `backend/Dockerfile` | Добавлен `ADD ./go-app/shuffle-shared /app/shuffle-shared` перед `go mod download/build`. |
| `backend/go-app/shuffle-shared/` | Полная копия модуля `shuffle-shared v1.2.51` с патчами. |
> Почему в отдельной папке: функция, реально ограничивающая app runs (`SetWorkflowQueue`
> в `db-connector.go`), и лимиты суб-организаций живут во внешнем модуле
> `github.com/shuffle/shuffle-shared`. Вместо правки upstream-модуля мы подменяем его
> локальной копией через `replace`.
Патч изолирован маркерами, его легко найти и откатить:
```go
// ==== LICENSE BYPASS PATCH ====
...
// ==== END LICENSE BYPASS PATCH ====
```
### Покрытие (аудит всех точек принуждения)
Пропатчены **все** источники правды о лицензии, которые реально ограничивают работу:
| Точка принуждения | Файл | Покрытие |
|-------------------|------|----------|
| Лимит app runs | `db-connector.go` `SetWorkflowQueue` (~8819) | Через `HandleCheckLicense` + `checkNoInternet` (патчи) |
| Лимит app runs (облако) | `cloudSync.go` (~947) | Через `SyncFeatures.AppExecutions.Limit` = 1e9 (патч HandleCheckLicense) |
| Лимит окружений (multi-env) | `db-connector.go` (~7388) | Через `SyncFeatures.MultiEnv` = активный (патч HandleCheckLicense) |
| Лимит суб-организаций | `shared.go` (~13084, 13093) | Через `checkNoInternet` + `HandleCheckLicense` (оба патча) |
| UI-флаг "licensed" | `main.go:1087` / `IsLicensed` | Патч `IsLicensed` = true |
Прочие чтения `SyncFeatures`/лимитов (дефолты, описания, `BuildBaseSubscription`) не блокируют работу — это только отображение в UI. Проверяющие агенты (worker/orborus) лицензию не проверяют.
---
## Как собрать и запустить
Важно: **docker build context — `backend/`** (как в CI Shuffle), НЕ корень репозитория.
### 1. Взять готовый образ (рекомендуется)
Патченый образ публикуется в registry как `marker689/shuffle-backend-unchained:12082026`.
Просто укажите его в `docker-compose.yml` (см. шаг 2) — docker сам его скачает.
Либо собрать локально:
```bash
cd backend
docker build -t marker689/shuffle-backend-unchained:12082026 -f Dockerfile .
```
### 2. Подключить образ к docker-compose
В `docker-compose.yml` у сервиса `backend` заменить образ на готовый патченый:
```yaml
image: marker689/shuffle-backend-unchained:12082026
```
> Это уже собранный и пропатченный образ (публичный в registry `marker689`).
> Альтернатива — собрать локально: `cd backend && docker build -t ... -f Dockerfile .`.
### 3. Запустить
```bash
docker-compose up -d
```
Ключ `SHUFFLE_LICENSE` в `.env` можно **не указывать** — патч его игнорирует.
---
## Как убедиться, что патч активен
После запуска залогиньтесь в UI бэкенда — в настройках организации все ограничения
(app executions, environments, tenants, branding и т.д.) будут показываться как активные/безлимитные.
Проверка собранного бинаря:
```bash
docker run --rm --entrypoint sh marker689/shuffle-backend-unchained:12082026 \
-c 'grep -c "LICENSE BYPASS PATCH" /app/shuffle-shared/shared.go && grep "shuffle-shared =>" /app/go.mod'
```
Ожидаемый вывод:
```
4
replace github.com/shuffle/shuffle-shared => ./shuffle-shared
```
(`shared.go` — 4 маркера патча в двух функциях; `db-connector.go` — 2 маркера в `checkNoInternet`.)
---
## Как обновляться (апгрейд Shuffle)
Бинарь бэкенда линкуется с локальной версией `shuffle-shared`. При апгрейде Shuffle:
1. Узнайте актуальную версию, которую требует новый `backend/go-app/go.mod` (поле `require`).
2. Скачайте исходники этой версии:
```bash
curl -L -o shuffle-shared.zip \
"https://proxy.golang.org/github.com/shuffle/shuffle-shared/@v/<VERSION>.zip"
```
3. Замените `backend/go-app/shuffle-shared/` новым содержимым.
4. Повторите патчи в трёх местах (см. блоки ниже).
5. Пересоберите образ.
### Патч 1 — в `HandleCheckLicense` (сразу после `func ... {`)
```go
// ==== LICENSE BYPASS PATCH ====
org.Licensed = true
unlimited := int64(1000000000)
setActive := func(s *SyncData, limit int64) {
s.Active = true
s.Limit = limit
}
setActive(&org.SyncFeatures.AppExecutions, unlimited)
setActive(&org.SyncFeatures.OnpremAppExecutions, unlimited)
setActive(&org.SyncFeatures.MultiEnv, unlimited)
setActive(&org.SyncFeatures.MultiTenant, unlimited)
setActive(&org.SyncFeatures.MultiRegion, unlimited)
setActive(&org.SyncFeatures.Webhook, unlimited)
setActive(&org.SyncFeatures.Schedules, unlimited)
setActive(&org.SyncFeatures.UserInput, unlimited)
setActive(&org.SyncFeatures.SendMail, unlimited)
setActive(&org.SyncFeatures.SendSms, unlimited)
setActive(&org.SyncFeatures.Updates, unlimited)
setActive(&org.SyncFeatures.EmailTrigger, unlimited)
setActive(&org.SyncFeatures.Notifications, unlimited)
setActive(&org.SyncFeatures.Workflows, unlimited)
setActive(&org.SyncFeatures.Autocomplete, unlimited)
setActive(&org.SyncFeatures.WorkflowExecutions, unlimited)
setActive(&org.SyncFeatures.Authentication, unlimited)
setActive(&org.SyncFeatures.Schedule, unlimited)
setActive(&org.SyncFeatures.Apps, unlimited)
setActive(&org.SyncFeatures.ShuffleGPT, unlimited)
setActive(&org.SyncFeatures.Branding, unlimited)
setActive(&org.SyncFeatures.AgentExecutions, unlimited)
setActive(&org.SyncFeatures.AgentTokens, unlimited)
return org
// ==== END LICENSE BYPASS PATCH ====
```
### Патч 2 — в `IsLicensed` (сразу после `func ... {`)
```go
func IsLicensed(ctx context.Context, org Org) bool {
// ==== LICENSE BYPASS PATCH ====
return true
// ==== END LICENSE BYPASS PATCH ====
```
Оставшийся код тела функции остаётся неактивным (недостижимым).
### Патч 3 — в `checkNoInternet` (сразу после инициализации `license`)
```go
// ==== LICENSE BYPASS PATCH ====
license.Valid = true
license.Environment.Active = true
license.Environment.Limit = 1000000000
license.Tenant.Active = true
license.Tenant.Limit = 1000000000
license.AppRuns.Active = true
license.AppRuns.Limit = 1000000000
license.Branding = true
license.Timeout = "01-01-2100"
return license
// ==== END LICENSE BYPASS PATCH ====
```
Этот ранний возврат делает всю дальнейшую проверку `SHUFFLE_LICENSE` недостижимой — он закрывает прямые чтения `checkNoInternet()` в `SetWorkflowQueue` (app runs) и в проверке лимита суб-организаций, которые **не идут через `HandleCheckLicense`** и не были бы закрыты патчем 1.
---
## Откат патча
Чтобы вернуть стоковое поведение:
1. Удалить строку `replace github.com/shuffle/shuffle-shared => ./shuffle-shared` из `backend/go-app/go.mod`.
2. Удалить папку `backend/go-app/shuffle-shared/`.
3. Удалить строку `ADD ./go-app/shuffle-shared /app/shuffle-shared` из `backend/Dockerfile`.
4. Пересобрать образ.