SurrealDB, licencja BSL i dostęp z przeglądarki
SurrealDB to baza danych napisana w Rust, która w jednym silniku obsługuje dokumenty, grafy, tabele relacyjne i pary klucz-wartość, a klient potrafi połączyć się z nią wprost z przeglądarki przez WebSocket. Silnik wychodzi na Business Source License 1.1, czyli licencji, która nie jest otwarta, i od niej zaczyna się każda decyzja o wdrożeniu.
Co SurrealDB robi i czego nie robi
Silnik wystawia jeden język zapytań, SurrealQL, i jeden zestaw poleceń definiujących schemat: DEFINE TABLE, DEFINE FIELD, DEFINE INDEX, DEFINE ACCESS, DEFINE USER, DEFINE SEQUENCE. Rekordy mają identyfikatory złożone z nazwy tabeli i klucza, powiązania między nimi zapisuje instrukcja RELATE, a subskrypcje na zmiany wystawia LIVE SELECT. Uwierzytelnianie siedzi w tym samym procesie, więc osobnej warstwy autoryzacji nie trzeba pisać.
Bazę uruchamia się jako serwer albo osadza w aplikacji w Rust. Magazyn wybiera się cechami kompilacji: w crate surrealdb w wersji 3.2.4 są to kv-mem, kv-rocksdb, kv-surrealkv, kv-indxdb oraz kv-tikv. Domyślny zestaw cech to protocol-ws i rustls, a osobno włącza się protocol-http, scripting, ml, jwks i http.
[dependencies]
surrealdb = { version = "3.2.4", default-features = false, features = ["protocol-http", "rustls"] }Czego SurrealDB nie robi, jest równie ważne. Nie zastępuje PostgreSQL tam, gdzie liczy się dojrzały planista zapytań i dwadzieścia lat narzędzi dookoła. Nie jest wyspecjalizowaną bazą wektorową w rozumieniu Qdrant, choć ma indeksy wektorowe. Nie jest też gotowym backendem w stylu PocketBase, bo panel administracyjny i reguły dostępu to dwie różne rzeczy.
Business Source License 1.1, przeczytana wprost
Plik LICENSE w korzeniu repozytorium surrealdb/surrealdb zawiera pełny tekst Business Source License 1.1 z nagłówkiem parametrów. Licencjodawcą jest SurrealDB Ltd., objęte dzieło opisane jest jako SurrealDB 3.0 z prawami autorskimi SurrealDB Limited z 2025 roku, Change Date przypada na 1 stycznia 2030 roku, a Change License to Apache License 2.0. Sam tekst licencji stwierdza wprost, że nie jest to licencja otwarta.
Prawa, które BSL daje bez żadnych warunków, są węższe, niż się wydaje przy pobieżnym czytaniu: kopiowanie, modyfikowanie, tworzenie dzieł zależnych, redystrybucja i użycie nieprodukcyjne. Użycie produkcyjne jest dozwolone tylko w zakresie, jaki wyznacza parametr Additional Use Grant, i to on jest sednem sprawy.
Additional Use Grant w tym repozytorium mówi, że wolno używać objętego dzieła pod warunkiem, że nie używa się go jako Database Service. Definicja jest dopisana w tym samym akapicie: chodzi o dowolny produkt, usługę, platformę lub ofertę komercyjną, w której SurrealDB dostarcza funkcje bazodanowe stronom trzecim, innym niż własni pracownicy i kontraktorzy działający na twoje zlecenie, w sposób pozwalający tym stronom trzecim tworzyć schematy i tabele, zarządzać nimi lub je kontrolować.
Przełożenie na konkretne przypadki wygląda tak. Aplikacja SaaS, w której to ty definiujesz schemat, a klienci tylko wprowadzają dane, mieści się w dozwolonym zakresie. Wewnętrzna analityka dla własnych pracowników mieści się, bo pracownicy są z definicji stron trzecich wyłączeni. Hosting SurrealDB sprzedawany klientom nie mieści się. Platforma niskokodowa albo backend jako usługa, w której najemcy sami definiują swoje tabele, też się nie mieści, a to jest dokładnie ta klasa produktu, przy której SurrealDB wygląda najbardziej kusząco. Kto buduje coś takiego, potrzebuje osobnej umowy licencyjnej od producenta.
Data przekształcenia działa osobno dla każdej wersji. Licencja mówi, że prawa z Change License wchodzą w Change Date albo w czwartą rocznicę pierwszej publicznej dystrybucji danej wersji, zależnie od tego, co nastąpi wcześniej. Wersja 3.2.4 ukazała się 3 sierpnia 2026 roku, więc jej czwarta rocznica przypada 3 sierpnia 2030 roku, a Change Date wypada 1 stycznia 2030 roku i to ta data jest wcześniejsza. Ta konkretna wersja stanie się więc kodem na Apache 2.0 pierwszego stycznia 2030 roku. Starsze linie mają własne parametry: plik licencyjny pod tagiem v2.3.7 opisuje objęte dzieło jako SurrealDB 2.0 i podaje Change Date 17 września 2029 roku. Nie ma jednej daty dla całego projektu.
Trzy klauzule dopełniają obrazu. Licencję trzeba widocznie umieścić przy każdej kopii, oryginalnej i zmodyfikowanej. Naruszenie warunków wygasza prawa nie tylko do bieżącej wersji, ale do wszystkich wersji objętego dzieła. Licencja nie daje żadnych praw do znaku towarowego ani logo producenta, poza użyciem, którego sama wymaga.
Trzy źródła licencji i to, co się nie zgadza
Przy audycie zależności sprawdza się trzy miejsca, bo potrafią się rozjeżdżać.
| Źródło | Co pokazuje dla SurrealDB |
|---|---|
| Plik w repozytorium | LICENSE w korzeniu, pełny tekst BSL 1.1 |
| Rejestr pakietów | crates.io podaje non-standard dla surrealdb, surrealdb-core, surrealdb-types |
| Opublikowany artefakt | paczka .crate wersji 3.2.4 zawiera plik LICENSE z tekstem BSL 1.1 |
Pierwsze źródło jest jednoznaczne. Sprawdziłem także warianty pisowni i pliki opisujące układ licencyjny: LICENSE.md, LICENSING.md, NOTICE i COPYING w korzeniu gałęzi głównej zwracają 404, więc nie ma dodatkowego dokumentu zmieniającego obraz.
Drugie źródło wygląda podejrzanie, ale ma prozaiczne wyjaśnienie. Cargo.toml opublikowanej paczki nie podaje identyfikatora SPDX w polu license, tylko license-file = "LICENSE". Rejestr crates.io nie ma wtedy nazwy do wyświetlenia i wpisuje non-standard. Skanery zależności, które ufają polu z rejestru, pokażą więc dla SurrealDB nic nieznaczący ciąg zamiast BSL. Jeśli prowadzisz w firmie listę licencji, wpisz tam ręcznie Business Source License 1.1 wraz z Change Date, bo automat tego nie zrobi.
Trzecie źródło potwierdza deklarację. Rozpakowana paczka surrealdb w wersji 3.2.4 zawiera plik LICENSE z tekstem BSL 1.1, katalog src z siedemdziesięcioma trzema plikami .rs, katalogi benches i tests, build.rs, Cargo.lock oraz README.md. Kod jest w paczce, plik licencyjny jest w paczce i jego treść zgadza się z tym, co leży w repozytorium.
Po stronie JavaScriptu ten sam test wypada gorzej. Paczka npm surrealdb w wersji 2.0.8 deklaruje w package.json licencję Apache-2.0, a jej archiwum zawiera dokładnie siedem plików i nie ma wśród nich żadnego pliku licencyjnego.
npm pack surrealdb@2.0.8
tar tzf surrealdb-2.0.8.tgz
# package/package.json
# package/README.md
# package/dist/surrealdb.cjs, .d.ts, .mjs, surrealdb.server.cjs, surrealdb.server.mjsTekst Apache 2.0 leży w repozytorium surrealdb/surrealdb.js, ale nie trafia do artefaktu. Jeśli twój proces zgodności wymaga pliku licencyjnego wewnątrz dystrybuowanej paczki, ta go nie ma. Pakiet dla Pythona ma inny brak: metadane na PyPI dla wersji 2.0.0 nie zawierają ani pola license, ani klasyfikatora licencji, a plik LICENSE w repozytorium surrealdb/surrealdb.py to Apache 2.0.
Klienty mają inną licencję niż serwer
To rozróżnienie decyduje o tym, co realnie wchodzi do twojego produktu.
| Element | Wersja | Licencja |
|---|---|---|
Serwer i crate surrealdb | 3.2.4 | BSL 1.1 |
Crate surrealdb-core, surrealdb-types | 3.2.4 | BSL 1.1 |
Pakiet npm surrealdb | 2.0.8 | Apache 2.0 |
Pakiet PyPI surrealdb | 2.0.0 | Apache 2.0 wedle repozytorium |
Rustowy zestaw deweloperski nie jest wyjątkiem od BSL, tylko jego częścią. Crate surrealdb w wersji 3.2.4 zależy od surrealdb-core, surrealdb-types i surrealdb-types-derive, wszystkich przypiętych do tej samej wersji 3.2.4, i każdy z nich niesie w paczce ten sam plik BSL. Rozpakowałem surrealdb-types w wersji 3.2.4 i tekst licencyjny jest identyczny, z tą samą Change Date. Klient w Rust to więc kod na BSL, a nie permisywna biblioteka.
Zestawy dla JavaScriptu i Pythona są na Apache 2.0, czyli licencji permisywnej. Kod, który wysyłasz do przeglądarki, jest wolny od ograniczeń BSL. Ograniczenie dotyczy serwera, który uruchamiasz.
Warstwa zależności pakietu npm jest cienka i to widać w metadanych: jedna zależność produkcyjna, @surrealdb/sqon w dokładnej wersji 0.1.0, oraz zależności równorzędne typescript w zakresie ^5.0.0 || ^6.0.0 i tslib w zakresie ^2.6.3. Pole engines nie istnieje, więc pakiet nie deklaruje minimalnej wersji Node. Przypięta zależność w linii zero oznacza, że poprawka w @surrealdb/sqon wymaga nowego wydania głównego pakietu.
Wersje, czyli co dziś jest stabilne
Numer wersji trzeba czytać uważnie, bo najnowsze wydania na liście są przedpremierowe.
curl -s -H "User-Agent: check" https://crates.io/api/v1/crates/surrealdb | \
python3 -c "import json,sys; c=json.load(sys.stdin)['crate']; print(c['max_stable_version'], c['newest_version'])"
# 3.2.4 3.3.0-beta.3Najnowsza wersja stabilna to 3.2.4, opublikowana 3 sierpnia 2026 roku. Linia 3.3.0 istnieje wyłącznie jako beta: 3.3.0-beta.1 z 14 sierpnia, 3.3.0-beta.2 z 18 sierpnia i 3.3.0-beta.3 z 20 sierpnia 2026 roku. Wcześniejsza kadencja wydań stabilnych była gęsta: 3.2.0 drugiego lipca, 3.2.1 dziesiątego lipca, 3.2.2 i 3.2.3 tego samego dnia 21 lipca, 3.2.4 trzeciego sierpnia. Wśród czternastu najnowszych wersji w rejestrze żadna nie jest oznaczona jako wycofana.
Daty z kanału wydań na GitHubie potrafią się rozjechać z rejestrem, bo znacznik czasu w tym kanale opisuje utworzenie lub edycję notatki, a nie publikację pakietu. Wpis dla wydania 3.2.4 ma tam znacznik z 18 sierpnia 2026 roku, podczas gdy paczka w rejestrze pochodzi z 3 sierpnia. Przy planowaniu wdrożenia bierz datę z rejestru.
Zgodność między wersjami to drugi powód, żeby patrzeć na tę linię uważnie. Dokumentacja producenta opisuje automatyczne migracje danych jako mechanizm dostępny dopiero od 3.3.0. Magazyn zapisuje wtedy wersję, która go ostatnio otwierała, i przed pierwszym zapytaniem stosuje zaległe migracje, rejestrowane w ledgerze obejmującym cały klaster. Konsekwencja jest jednokierunkowa: cofnięcie się do starszego wydania zostaje odrzucone, jeśli magazyn wykonał migrację, której starszy program nie zna, a powrót wymaga wtedy eksportu poleceniem surreal export i wczytania danych do magazynu założonego przez starszą wersję.
Pierwsza z tych migracji naprawia usterkę, którą warto znać przed wdrożeniem 3.2.x. Na wersjach od 3.0 do 3.2 układ kluczy dla DEFINE SEQUENCE nachodzi na tabele, których nazwa zaczyna się od sq. Baza z taką tabelą przestaje odpowiadać na INFO FOR DB, nie daje się usunąć poleceniem REMOVE DATABASE, więc zostaje nieusuwalna, a eksport obejmujący sekwencje kończy się błędem. Żadna sekwencja nie musi istnieć, żeby to wystąpiło. Poprawka jest w 3.3.0, czyli dziś w becie.
Numeracja zestawów deweloperskich nie idzie w parze z numeracją serwera. Serwer jest na 3.2.4, pakiet npm na 2.0.8 z 21 lipca 2026 roku, a stabilny pakiet PyPI na 2.0.0 z 23 kwietnia 2026 roku, przy czym w rejestrze wiszą też przedpremierowe wydania 3.0.0b8. W pliku README pakietu npm nie znalazłem tabeli zgodności z wersjami serwera, więc parowanie konkretnego zestawu z konkretnym serwerem traktuj jako rzecz do przetestowania, a nie do założenia.
Dostęp z przeglądarki i uprawnienia w SurrealQL
Wyróżnik SurrealDB polega na tym, że przeglądarka łączy się z bazą bez własnego backendu. Wygląda to tak:
import { Surreal } from "surrealdb"
const db = new Surreal()
await db.connect("wss://my-instance.aws-euw1.surreal.cloud")
await db.use({ namespace: "test", database: "test" })
await db.signin({ username: "root", password: "root" })Ostatnie wywołanie w tej postaci jest właśnie tym błędem, który kończy się wyciekiem, i to z powodu wbudowanego w silnik podziału tożsamości. SurrealDB zna użytkowników systemowych, definiowanych przez DEFINE USER na poziomie root, przestrzeni nazw albo bazy, oraz użytkowników rekordowych, definiowanych przez DEFINE ACCESS z typem RECORD. Uprawnienia tabel obowiązują tylko tych drugich. W kodzie wykonawczym wersji 3.2.4 sprawdzenie dla użytkownika systemowego sprowadza się do tego, czy ma on rolę pozwalającą czytać lub zmieniać dane i czy docelowa przestrzeń nazw oraz baza mieszczą się w jego poziomie. Klauzula PERMISSIONS nie jest wtedy w ogóle brana pod uwagę. Poświadczenia root w przeglądarce dają więc pełny odczyt i zapis niezależnie od tego, co napisałeś przy tabelach.
Domyślne ustawienie samo w sobie jest zamknięte. Parser wersji 3.2.4 przypisuje tabeli zdefiniowanej bez klauzuli PERMISSIONS wartość NONE dla wszystkich czterech operacji, więc użytkownik rekordowy nie zobaczy nic, dopóki nie napiszesz reguły. Wyciek nie bierze się z domyślnej wartości, tylko z PERMISSIONS FULL wpisanego na czas rozwoju i zapomnianego, albo z klucza administracyjnego w pakiecie frontendu.
DEFINE ACCESS user ON DATABASE TYPE RECORD
SIGNUP ( CREATE user SET email = $email, pass = crypto::argon2::generate($pass) )
SIGNIN ( SELECT * FROM user WHERE email = $email AND crypto::argon2::compare(pass, $pass) )
DURATION FOR TOKEN 15m, FOR SESSION 12h;
DEFINE TABLE note SCHEMAFULL
PERMISSIONS
FOR select, update, delete WHERE owner = $auth.id
FOR create WHERE $auth.id != NONE;Parametr $auth jest nazwą chronioną w silniku, obok $access, $token i $session, i wskazuje rekord, na który wystawiono sesję. DURATION przyjmuje osobne wartości dla tokenu i dla sesji, a przy typach dostępu wystawiających uprawnienia także dla nich. Instrukcja DEFINE ACCESS obsługuje warianty OVERWRITE oraz IF NOT EXISTS, co ma znaczenie przy migracjach schematu.
Skala szkody przy błędzie jest pełna, bo klient wysyła dowolne SurrealQL. Metoda db.query przyjmuje ciąg znaków, więc po stronie serwera nie ma listy dozwolonych zapytań, którą można by potraktować jako drugą linię obrony. Ktokolwiek otworzy narzędzia deweloperskie, zobaczy ramki WebSocket i powtórzy je z tym samym tokenem. Przy tabeli na PERMISSIONS FULL oznacza to odczyt wszystkich rekordów i możliwość ich skasowania. Jest jeszcze jeden przypadek graniczny: gdy uwierzytelnianie serwera jest wyłączone, a sesja jest anonimowa, sprawdzanie uprawnień w ogóle się nie odbywa. Taki tryb bywa wygodny lokalnie i bywa katastrofą wystawiony na publiczny adres.
Model dostępu jest tu bliższy PocketBase i Supabase niż klasycznej bazie, ale różnica jest istotna. W Supabase reguły pisze się jako polityki dostępu w bazie relacyjnej, w PocketBase jako wyrażenia reguł na kolekcji, a w SurrealDB jako klauzule w definicji tabeli. We wszystkich trzech przypadkach pusta lub zbyt szeroka reguła jest jedyną rzeczą dzielącą dane od internetu.
Cennik Surreal Cloud
Strona cennika producenta renderuje treść planów bez JavaScriptu, więc liczby dają się odczytać z surowego HTML. Interaktywny kalkulator działa dopiero po uruchomieniu skryptów i nie podaje w statycznej treści specyfikacji płatnych konfiguracji, więc ich nie zgaduję.
| Plan | Cena | Co zawiera |
|---|---|---|
| Start | 0 USD za godzinę, potem od 0,021 USD za godzinę | jedna darmowa instancja, 1 GB pamięci masowej i 1 GB ruchu wychodzącego miesięcznie bez opłat |
| Scale | 0,192 USD za węzeł na godzinę | wdrożenie w wielu strefach dostępności, skalowanie poziome |
| Enterprise | wycena indywidualna | wdrożenie własne, audyt, wsparcie |
Darmowa konfiguracja w kalkulatorze to 0,25 vCPU i 1 GB pamięci operacyjnej za 0,000 USD za godzinę. Arytmetyka dla planów płatnych wygląda tak: 0,021 USD za godzinę przy 730 godzinach w miesiącu daje około 15,33 USD miesięcznie za najtańszą płatną instancję, a 0,192 USD za węzeł na godzinę daje około 140,16 USD miesięcznie za węzeł, czyli około 420,48 USD miesięcznie za trzy węzły, zanim doliczysz pamięć masową i ruch wychodzący. Dodatek Agent Memory ma osobne plany samoobsługowe od 29 USD miesięcznie z tygodniowym okresem próbnym.
Dwie pozycje na liście funkcji planów Start i Scale są oznaczone gwiazdką opisaną jako wkrótce, w tym rozgałęzianie bazy danych. Traktuj je jako zapowiedź, nie jako coś, na czym można oprzeć plan wdrożenia.
SurrealDB a alternatywy
| Rozwiązanie | Model danych | Licencja silnika | Klient w przeglądarce |
|---|---|---|---|
| SurrealDB 3.2.4 | dokument, graf, relacje, klucz-wartość | BSL 1.1, Apache 2.0 od 2030-01-01 | tak, WebSocket |
| PostgreSQL | relacyjny plus rozszerzenia | permisywna | nie, przez warstwę pośrednią |
| MongoDB Community | dokumentowy | SSPL wersja 1 | nie bezpośrednio |
| Neo4j | graf natywny, Cypher | społecznościowa lub komercyjna | nie bezpośrednio |
| PocketBase | relacyjny na SQLite | MIT | tak, przez REST |
| Supabase | relacyjny na PostgreSQL | permisywna | tak, przez REST i realtime |
SurrealDB wygrywa tam, gdzie ten sam zbiór danych trzeba czytać raz jak dokument, raz jak graf, a jednocześnie chcesz mieć jeden proces zamiast trzech. Zapytanie łączące przejście po powiązaniach z filtrem po polach dokumentu i z podobieństwem wektorowym jest w SurrealQL jednym zapytaniem, a w stosie złożonym z PostgreSQL, Neo4j i Qdrant to trzy zapytania i kod scalający wyniki, plus synchronizacja trzech kopii danych.
Przegrywa tam, gdzie ryzyko liczy się bardziej niż wygoda. Licencja wyklucza całą klasę produktów. Linia stabilna nie ma jeszcze automatycznych migracji. Ekosystem narzędzi operacyjnych jest młody w porównaniu z tym, co ma PostgreSQL czy nawet Redis. Jeśli głównym argumentem jest szybki start z dostępem z klienta, PocketBase i Supabase robią to samo na licencjach, których nie trzeba tłumaczyć prawnikowi.
Typowe błędy
Nazywanie SurrealDB projektem open source. BSL nie jest licencją otwartą i mówi to o sobie wprost. Jeśli w prezentacji dla zarządu pada słowo otwarty, ktoś podejmie decyzję na fałszywej przesłance.
Pominięcie Additional Use Grant przy produkcie wielodostępnym. Ograniczenie nie dotyczy sprzedawania oprogramowania w ogóle, tylko dawania stronom trzecim możliwości tworzenia schematów i tabel oraz zarządzania nimi. Produkt, w którym najemcy projektują własne modele danych, wpada w to ograniczenie.
Przepisanie do rejestru licencji wartości non-standard z crates.io. To artefakt braku identyfikatora SPDX, a nie nazwa licencji. Wpis powinien brzmieć Business Source License 1.1 wraz z Change Date.
Wysyłanie do przeglądarki poświadczeń użytkownika systemowego. Konto root ignoruje klauzule PERMISSIONS, więc żadna reguła przy tabeli nie ochroni danych przed kimś, kto odczyta klucz z pakietu frontendu.
Zostawienie PERMISSIONS FULL po fazie rozwoju. Domyślna wartość dla tabeli bez tej klauzuli jest zamknięta, więc szeroka reguła zawsze jest czyimś świadomym wpisem, tylko zapomnianym.
Założenie, że numer wersji zestawu deweloperskiego odpowiada wersji serwera. Pakiet npm 2.0.8 współpracuje z serwerem 3.2.4, a te numery nie mają ze sobą związku.
Utworzenie na wersjach od 3.0 do 3.2 tabeli o nazwie zaczynającej się od sq. Skutkiem jest baza, której nie da się usunąć ani opisać poleceniem INFO FOR DB.
FAQ
Czy SurrealDB jest oprogramowaniem open source?
Nie. Silnik wychodzi na Business Source License 1.1, a tekst tej licencji sam stwierdza, że nie jest licencją otwartą, i zapowiada jedynie, że objęte dzieło stanie się nią w przyszłości. Zestawy deweloperskie dla JavaScriptu i Pythona są osobną sprawą i mają licencję Apache 2.0.
Czy mogę użyć SurrealDB w komercyjnym produkcie?
Tak, o ile produkt nie jest usługą bazodanową w rozumieniu Additional Use Grant. Aplikacja, w której to ty ustalasz schemat, a klienci wprowadzają dane, mieści się w dozwolonym zakresie. Platforma, w której klienci sami tworzą tabele i nimi zarządzają, wymaga osobnej umowy z producentem.
Kiedy kod stanie się dostępny na Apache 2.0?
Change Date w bieżącym pliku licencyjnym to 1 stycznia 2030 roku, a licencja docelowa to Apache 2.0. Data liczy się osobno dla każdej wersji i wchodzi w życie nie później niż w czwartą rocznicę pierwszej publicznej dystrybucji danej wersji. Linia 2.x ma w swoim pliku Change Date 17 września 2029 roku.
Którą wersję wdrożyć dziś?
Stabilna jest 3.2.4 z 3 sierpnia 2026 roku. Linia 3.3.0 to na razie trzy wydania przedpremierowe i wnosi automatyczne migracje danych oraz poprawkę usterki z tabelami o nazwach zaczynających się od sq. Wdrożenie bety na produkcję dla jednej poprawki jest wymianą jednego ryzyka na inne.
Czy dostęp z przeglądarki jest bezpieczny?
Jest bezpieczny wtedy, gdy przeglądarka loguje się jako użytkownik rekordowy zdefiniowany przez DEFINE ACCESS typu RECORD, a każda tabela ma klauzulę PERMISSIONS odnoszącą się do $auth. Konta systemowe pomijają te klauzule, więc klucz administracyjny w kodzie frontendu daje pełny dostęp do bazy.
Czy dane trzeba przeładowywać przy aktualizacji?
Przy przejściu w górę do 3.3.0 nie, bo magazyn stosuje zaległe migracje sam przed pierwszym zapytaniem. Przy cofnięciu się do starszego wydania tak: serwer odmawia otwarcia magazynu, który wykonał nieznaną mu migrację, i trzeba wyeksportować dane oraz wczytać je do magazynu założonego przez starszą wersję.